Thread safe operations on table in pl/sql procedure?

I am developing java application which will be running in N localizations simultaneously, each application will have M threads. Every thread takes an unique ID with status NOT_TAKEN from table Queue and changes its status to TAKEN.
Problem:
How to prevent thread from situation like this:
1. Thread A select first ID with status NOT_TAKEN
2. In the same time thread B select first (so it will be the same ID which selected thread A) ID with status NOT_TAKEN.
3. Thread A changes status of ID to TAKEN
4. Thread B changes status of ID to TAKEN
After this operation thread A and B are using the same ID.
What I did:
I have written pl/sql procedure which lock table Queue in exclusive mode, selects first ID, changes its status to TAKEN and unlocks the table. Because it is lock in exclusive mode so only one thread can run this procedure simultaneously.
Question:
How optimally should it be solved, because mine solution prevents from doing all other Updates on Queue table while it is locked, like changing status from TAKEN to OPERATION_DONE so it has performance issue.

As Centinul has said, you need to lock just one row.
I would just add NOWAIT to the select statement to let the Java thread go and try again, instead of waiting for the other threads.
Example: (not tested)
-- Assuming structure of your QueueTable: ( IDCol is PK , StatusCol is VARCHAR2, ... )
-- or make it part of the package....
CREATE OF REPLACE
FUNCTION updateQueue( nQID QueueTable.IDCol%TYPE) RETURN VARCHAR2 AS
   eLocked EXCEPTION;
   PRAGMA EXCEPTION_INIT(eLocked,-54);
   CURSOR curQueueTable IS SELECT 1 CNTR FROM QueueTable WHERE IDCol=nQID AND StatusCol='NOT_TAKEN' FOR UPDATE OF StatusCol NOWAIT;
   recQueueTable curQueueTable%ROWTYPE;
   cRtn VARCHAR2(1);
BEGIN
   cRtn := 'Y';
   BEGIN
      OPEN curQueueTable;
      FETCH curBuffSummary INTO recQueueTable;
      CLOSE curQueueTable;
      IF recQueueTable.CNTR IS NOT NULL AND recQueueTable.CNTR = 1 THEN
          UPDATE QueueTable SET StatusCol = 'TAKEN' WHERE IDCol=nQID;
      ELSE
          -- Already updated
          cRtn := 'N';
      END IF;
         -- You can control your transaction here as well
         -- COMMIT;
         -- But if realy should be done in the Java thread.
    EXCEPTION
       WHEN eLocked OR STANDARD.TIMEOUT_ON_RESOURCE THEN
       -- Thread could not get exclusice row lock. Ignore error.
         cRtn := 'N';
         NULL;
      WHEN OTHERS THEN
         -- Handle other errors...
         -- NULL; just kidding...
         RAISE;
   END;
   RETURN cRtn;
END; Edited by: thomaso on Sep 18, 2009 10:30 AM

Similar Messages

  • Reading Text file & Updating table using PL SQL Procedure

    Guys, I am trying to read data from a large text file which
    contains tab delimited data. Based on success of validations, I
    have to insert/update data in to table(s). Does any one has any
    sample procedure to read data (tab delimted/comma seperated)
    from a text file and write to database table? Your help is
    greatly appreciated!

    Is there any particular reason why you're not using SQL*Loader
    for this? Otherwise you would seem to be re-inventing the wheel.
    rgds, APC

  • Ceating table using PL/SQL procedure?

    Hello.
    I need to run a process (in Oracle) which creates some tables according to some specific logic. Before creating those tables I would like to check if it already exists and if it does - to drop it.
    (when trying to do it I got an error : 'ORA-01031' insufficient privileses)
    I was reading some forums on the net and I understand that it is a bad practise to create tables from Procedures in Oracle.
    Please advice which other option I have.
    Thanks!

    Thans for your responses.
    Example of what I need:
    create table TABLE1 as select * from
    SELECT TABLE1.x, TABLE2.y
    FROM TABLE1
    INNER JOIN TABLE2 ON TABLE1.X=TABLE2.X
    ... (it's just a short example. the query i use i much longer and more difficult).
    I need to create ~10 tables on the same manner.
    It has to be a kind of daily process. But if by mistake this table was previously deleted - I will get an error when dropping it. That's why I need to use a kind of condition in order to check this.
    Please let me know which alternatives I have.
    Thanks.

  • Is SunONE Directory Thread-Safe?

    Is SunONE Directory Thread-Safe?
    If SunONE Directory is not Thread-Safe, is it the same case with other LDAP compatiable Directory Server?
    If it is not thread-safe, then it is up to the programmers to make all the calls in a synchronized manner, right?

    Is SunONE Directory Thread-Safe?Are you talking about the Server or the Client side library ?
    The server is thread safe, operations are processed in parallele.
    >
    If SunONE Directory is not Thread-Safe, is it the
    same case with other LDAP compatiable Directory
    Server?Not Applicable.
    >
    If it is not thread-safe, then it is up to the
    programmers to make all the calls in a synchronized
    manner, right?This is up to the application you want to build.
    Regards,
    Ludovic.

  • Create temp table in PL/SQL

    How to create temp table in PL/SQL procedure/function?
    In SQL plus, I can create a table using
    create table <table name>
    on commit reserve ..

    If you're referring to temp table similar as the temp table of informix .. the answer is you cannot create a temp table in oracle than will automatically be cleaned by oracle session.
    However its possible to create a remporary table but this will be a permanent part of your schema.. and you'll be the one responsible for dropping this table.
    regards,
    Victor ([email protected])
    <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica">quote:</font><HR>Originally posted by Mike Chan:
    How to create temp table in PL/SQL procedure/function?
    In SQL plus, I can create a table using
    create table <table name>
    on commit reserve ..
    <HR></BLOCKQUOTE>
    null

  • Sending OS command from PL/SQL procedure

    "How can I send a operating system comand from PL/SQL procedure?
    I want to move , to copy , delete a file from a PL/sql procedure. i.e under unix send mv, cp or
    rm command";
    my e-mail is [email protected]

    take a look at
    http://asktom.oracle.com/pls/ask/f?p=4950:8:881946
    regards
    Freek D'Hooge
    "How can I send a operating system comand from PL/SQL procedure?
    I want to move , to copy , delete a file from a PL/sql procedure. i.e under unix send mv, cp or
    rm command";
    my e-mail is [email protected]

  • Trying to understand "thread-safe" w/ swing components

    The other day there was a big hullabaloo about some code I posted because I was calling JLabel.setText from a thread that wasn't the ui thread. On the other hand, this thread was the only thread making changes to the JLabel. My understanding is that in any kind of multi-threaded system, if you just have 1 writer / changer, then no matter how many readers there are, this is thread-safe. So why what I was doing not thread safe?
    Second question - JLabel.setText() is essentially setting data in the model for JLabel, which then gets picked up and displayed the next time the GUI thread paints it. So if it's not safe to update a JLabel's model, I assume its never safe to update any data that also is being displayed visually. So for instance, if I was showing some database table data in a JTable, I should do the update in the UI thread - probably not. But what is the distinction?
    Third question - what swing components and what operations need to be run on the UI thread to call your program "thread-safe". Validate? setSize()? setLocation()? add? remove? Is there anything that can be called on swing components from a non-ui thread?
    Edited by: tjacobs01 on Nov 2, 2008 8:29 PM

    tjacobs01 wrote:
    My understanding is that in any kind of multi-threaded system, if you just have 1 writer / changer, then no matter how many readers there are, this is thread-safe. So why what I was doing not thread safe?This is not true. As I mentioned in that hullabaloo thread, the Java Memory Model allows threads to cache values of variables they use. This means that values written by one thread are not guaranteed to ever be visible to other threads, unless you use proper synchronization.
    Take the following example:
    import java.util.concurrent.TimeUnit;
    public class ThreadExample {
        static class Foo {
            private String value = "A";
            public String getValue() {
                return value;
            public void setValue(String value) {
                this.value = value;
        public static void main(String[] args) {
            final Foo foo = new Foo();
            Thread writer = new Thread() {
                @Override
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        foo.setValue("B");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
            Thread reader = new Thread() {
                @Override
                public void run() {
                    try {
                        TimeUnit.MINUTES.sleep(1);
                        System.out.println(foo.getValue());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
            writer.start();
            reader.start();
    }Here two different threads both access the same Foo instance, which is initialized with a value of "A". One thread, the writer, sleeps one second, and then sets foo's value to "B". The other thread, the reader, sleeps one minute (to avoid race conditions) and then prints foo's value to System.out. It may seem obvious that the reader thread will read the value "B", but this is in fact not guaranteed to be true. The reader thread may never see the value that was written by the writer thread, so it may very well read the old value "A".
    (If you run the code you will probably see "B" printed out, but again, this is not guaranteed behavior.)
    A simple way to fix this is to synchronize access to the mutable state that the two threads share. For example, change the class Foo to
        static class Foo {
            private String value = "A";
            public synchronized String getValue() {
                return value;
            public synchronized void setValue(String value) {
                this.value = value;
        }It's for this same reason that you often see the use of a volatile boolean as a control flag for stopping threads, rather than a plain old boolean. The use of volatile guarantees that the thread you want to stop actually sees the new value of the flag once it has been set by another thread.
    Here is an article that touches some of this stuff:
    [http://www.ibm.com/developerworks/java/library/j-jtp02244.html]
    I also highly recommend the book "Java Concurrency in Practice" (one of the authors of which, David Holmes, sometime hangs out on the Concurrency forum here, I believe).
    Edited by: Torgil on Nov 2, 2008 9:01 PM

  • Hashtable really thread safe or is there a bug in it ?

    Hashtable is said to be thread-safe, so I think it should be true.
    So I just want someone to tell me what is wrong with my following observation:
    I downloaded the source code of jdk 1.3.1 and read the file Hashtable.java, that contains the implementation code of Hashtables.
    Lots of methods (like get(), put(), contains(), ...) are declared public and synchronized. So far, all is good.
    But the function size() is defined as follows:
    public int size() {
         return count;
    where count is an instance variable defined as follows:
    * The total number of entries in the hash table.
    private transient int count;
    As the function size() is not synchronized, it can retrieve the value of "count" when another method is in the process of updating it.
    For instance, the method put() (that is synchronized) increments the variable "count" with this instruction:
    count++;
    But we know that operation on variable of type "int" are atomic, so this issue doesn't harm the thread safety of the code.
    But there is another issue with multithreading, that deals with caching of data in the working memory of each thread.
    Suppose the following scenario:
    1) Thread A calls method size(). This method reads the value of "count" and put it in the working memory of thread A.
    2) Thread B calls method put(). This method increments "count" using instruction "count++".
    3) Thread A calls method size() again. This method reads the value of "count" from the working memory of the thread, and this cached value may not be the updated value by thread B.
    As size() is not synchronized, or "count" is not declared "volatile", multiple threads may retrieve stale value, because the content of the thread working memory is not in sync with main memory.
    So, here I see a problem.
    Is there something wrong in this observation ?
    But

    Is there something wrong in this observation ?Unfortunately not, as far as I can tell.
    Recent analysis of java's synchronized support has revealed the danger in such unsynchronized code blocks, so it may have been a simple case that it wasn't realised that size is not thread-safe.
    If this is an issue, use Collections.synchronizedMap - in Sun's JDK 1.3, at least, all of the methods are synchronized, except for iterators.
    Regards,
    -Troy

  • Is this code thread safe?

    I've been seeing some information that makes me think that some servlet code I have that I thought was thread-safe actually isn't. I have a servlet that takes a POST request and calls a stored procedure on a database to do some inserts.
    public void doPost(HttpServletRequest request, HttpServletResponse response)
      // Check validity of request then proceed.
      if (valid) { postPayment(request); }
    synchronized private void postPayment(HttpServletRequest request)
      /* Take some parameters from the request and call the stored procedure */
    }What I'm attempting to do is ensure that 2 requests with the same data don't attempt to insert to the database at the same time. Have I accomplished that or do I need a different approach?

    Meatwad wrote:
    What if I had a static synchronized java bean that a member variable of the servlet class?As stated in my previous post:
    even that wouldn't be enough if there's more than one server running your app.and
    Since it database operations that you want to make atomic, the right place to ensure that is in the database.and
    The database is the only place where you're guaranteed a shared point of access to the resources you're trying to protect, so that's the appropriate (only) place to provide that protection.For an academic exercise with a single server, and if no other servlet or app is modifying the relevant tables, your approach is probably sufficient. But when all is said and done, a database transaction is the appropriate way to ensure exclusivity and atomicity of database operations.
    EDIT: Now, when you say "java bean", if you in fact are referring to an EJB, then I think they have their own tools and idioms for exclusivity and atomicity that encompass Java level syncing and DB transactions. I'm don't know anything about that though.
    Edited by: jverd on Jun 22, 2011 10:23 AM

  • I am trying to have access tables of the Sql Server through the Oracle

    I am trying to have access tables of the Sql Server through the Oracle and this being occurred the error:
    ORA-28500: connection from ORACLE to a non-Oracle system returned this message: [Generic Connectivity using ODBC][H006] The init parameter <HS_FDS_CONNECT_INFO> is not set.
    Please set it in init <orasid>.ora file.
    ORA-02063: preceding 2 lines from HSMSQL
    I created the ODBC with name HSMSQL.
    I made all the configurations in the archives
    tnsnames.ora:
    HSMSQL=
    (DESCRIPTION=
    (ADDRESS= (PROTOCOL = tcp)(HOST = wsus)(PORT = 1521))
    (CONNECT_DATA =
    (SID = HSMSQL)
    (HS = OK)
    listener.ora:
    (SID_DESC = (SID_NAME=HSMSQL)
    (ORACLE_HOME= C:\oracle\ora92)
    (PROGRAM =hsodbc)
    initHS_SID.ora:
    HS_FDS_CONNECT_INFO = HSMSQL
    HS_FDS_TRACE_LEVEL = OFF
    -- Create database link
    create database link HSMSQL.US.ORACLE.COM
    connect to TESTE identified by TESTE2
    using 'HSMSQL';
    But when I execute query the error occurs:
    Select * from TabTeste@HSMSQL
    ORA-28500: connection from ORACLE to a non-Oracle system returned this message: [Generic Connectivity using ODBC][H006] The init parameter <HS_FDS_CONNECT_INFO> is not set.
    Please set it in init <orasid>.ora file.
    ORA-02063: preceding 2 lines from HSMSQL
    Please they help me, thanks, Paulo.

    Hi,
    It seems that your configuration is Ok. By the way, the workaround for this error is:
    ORA-28500: connection from ORACLE to a non-Oracle system returned this message:
    [Transparent gateway for ODBC][H001] The environment variable <HS_FDS_CONNECT_INFO> is not set.
    * Set HS_FDS_CONNECT_INFO in the hs{sid}init.ora file to the data source name.
    Example: HS_FDS_CONNECT_INFO = <ODBC DataSource Name>
    * Make sure the hs{sid}init.ora file exists in the ORACLE_HOME/hs/admin directory and has the same name as the SID in the LISTENER.ORA.
    Example: If SID=hsodbc in the listener.ora file, then the hs{sid}init.ora file would be named ORACLE_HOME/hs/admin/inithsodbc.ora
    For more information see if this [url http://forums.oracle.com/forums/thread.jspa?forumID=61&threadID=576975]thread can help you.
    Cheers

  • Calculation operations on table

    Hi all,
    Is there any way to identify calculation operation on column of table in CREATE TABLE statment. the arguments of operation it will take it from other table columns using SQL.
    e.g: x=y+z where y in table A and z in table B
    please help.
    regards,
    Mona

    As William was noting, you can do a calculation form more than one table at the time you create the table. But, those values in your new tbale will not change if the values in table_A and table_B (which were used in the calculation) change later.
    Maybe you were asking about another feature, new for 11g, whch allows you to create a virtual column. It permits you to create a column in a table which is entirely dependent on one or more other columns in the same table. When the values in those dependent coloumn(s) change, the virtual column changes, too. But: a virtual column can be based only on fields in the same table - you cannot reference other tables in the calculation.

  • Thread safe do-all class

    Hi,
    I'm new to Java programming and I've read through the forums and the numerous technical documents Sun has provided on how to make a GUI thread-safe. With what I've been able to understand, I created some template classes to handle the proper creation of JFrames, so I don't have to worry about playing with threads all the time. (I am operating under the assumption that invokeLater should handle the creation of all frames, not just the first window of the application).
    Since I'm not completely confident I've grasped the point, I was wondering if someone could look at this code to see if I've got the right idea. Your help would be much appreciated.
    Test.java
    import frames.*;
    public class Test
         public static void main(String args[])
              FrameOptions frameOpts = new FrameOptions("Options Window", 300, 400, true);
    frames\FrameOptions.java
    package frames;
    public class FrameOptions extends FrameTemplate
         public FrameOptions(String title, int width, int height, final boolean visible)
              super(title, width, height);
              javax.swing.SwingUtilities.invokeLater     (     new Runnable()
                                                 public void run()
                                                      createAndShow(visible);
         public void createAndShow(boolean visible)
              //Add all Swing components here.
              finishCreateAndShow(visible);
    frames\FrameTemplate.java
    package frames;
    import java.awt.Dimension;
    import javax.swing.JFrame;
    public class FrameTemplate extends JFrame
         public FrameTemplate(String title)
              super(title);
         public FrameTemplate(String title, int width, int height)
              super(title);
              doSize(width, height);
         private void doSize(int width, int height)
              Dimension d = new Dimension(width, height);
              setMinimumSize(d);
              setPreferredSize(d);
         protected void finishCreateAndShow(boolean visible)
              pack();
              setVisible(visible);
    }

    OK, makes sense now.
    For anyone else who may be new and wondering about this, this can be summed up as follows.
    Summary 1:
    If you create new frames from things such as menu events, you do not need to use invokeLater. Events are automatically done in the GUI thread/event dispatching thread. But if you're spawning these things from main() (or anything else not running in the EDT), you do.
    If you're ever unsure of which thread a block of code is running in, just drop a System.out.println(javax.swing.SwingUtilities.isEventDispatchThread()); into it.
    Summary 2:
    Don't use those classes I wrote. They're rather pointless unless you're spawning all of your frames from main, which I suspect most people would not be doing.
    Thanks for the clarification.
    public static void main(String args[])
    is run in a separate thread (separate from the GUi
    i thread). So if you need to do painting or other
    swing stuff from inside the main method, just use an
    invoke later. If you create a new frame from the GUI
    thread, you don't need to invoke later. Only if you
    do it from the main method (or some other non-GUI
    thread). Hope that helps

  • Thread Safe Pro*C++

    I want to have pro*C++ object that is thread safe. In a method of the object, I give the
    following code & get a pre-comipler error.
    xsaLaOracle::connect()
    /* declare the runtime context */
    sql_context ctx;
    /* enable threads */
    EXEC SQL ENABLE THREADS;
    /* allocate storage for the context */
    EXEC SQL CONTEXT ALLOCATE :ctx;
    /* other stuff happens here of course */
    The pre-compiler error tells me that ctx in the ALLOCATE statement is undefined. I pretty much just took this code straight from chapter 11 (Multithreaded Applications)
    of the Pro*C/C++ Precompiler Programmer's Guide. The examples in this chapter seem
    to have bugs, so I'm not sure if I'm doing
    something wrong, if the documentation is
    wrong or both!! With my luck probably both!!
    I am using Oracle & Pro*C/C++ 8.1.6 on
    Solaris 7 platform.
    If anyone has any ideas that would be great!
    Joe Longo
    null

    <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica">quote:</font><HR>Originally posted by Joseph Longo ([email protected]):
    I want to have pro*C++ object that is thread safe. In a method of the object, I give the
    following code & get a pre-comipler error.
    xsaLaOracle::connect()
    /* declare the runtime context */
    sql_context ctx;
    /* enable threads */
    EXEC SQL ENABLE THREADS;
    /* allocate storage for the context */
    EXEC SQL CONTEXT ALLOCATE :ctx;
    /* other stuff happens here of course */
    The pre-compiler error tells me that ctx in the ALLOCATE statement is undefined. I pretty much just took this code straight from chapter 11 (Multithreaded Applications)
    of the Pro*C/C++ Precompiler Programmer's Guide. The examples in this chapter seem
    to have bugs, so I'm not sure if I'm doing
    something wrong, if the documentation is
    wrong or both!! With my luck probably both!!
    I am using Oracle & Pro*C/C++ 8.1.6 on
    Solaris 7 platform.
    If anyone has any ideas that would be great!
    Joe Longo
    <HR></BLOCKQUOTE>
    Try this:
    xsaLaOracle::connect()
    /* declare the runtime context */
    EXEC SQL BEGIN DECLARE SECTION;
    sql_context ctx;
    EXEC SQL END DECLARE SECTION;
    /* enable threads */
    EXEC SQL ENABLE THREADS;
    /* allocate storage for the context */
    EXEC SQL CONTEXT ALLOCATE :ctx;
    /* other stuff happens here of course */
    null

  • Thread safe Timed Set

    Hello,
    I'm trying to create a thread safe set that also contains a time when it was updated last. It's a cache of a table from the db. I am using CopyOnWriteArraySet as the set is going to be modified rarely, items from set are never modified or removed individually.
    There are couple of questions, is the an existing collection that I can use to achieve the same in JDK 6 (not external libraries)? Is there a better choice over CopyOnWriteArraySet? I tried searching but couldn't find anything.
    If not, would the following implementation suffice my requirements?
    Any suggestions greatly appreciated.
    Thanks in advance,
    -t
    public class CacheSet<T> extends CopyOnWriteArraySet<T> {
    private static final long serialVersionUID = 1L;
    private long lastSyncTime = 0;
    * @param lastSyncTime
    *          the lastSyncTime to set
    public synchronized void setLastSyncTime(long lastSyncTime) {
    this.lastSyncTime = lastSyncTime;
    * @return the lastSyncTime
    public synchronized long getLastSyncTime() {
    return lastSyncTime;
    }

    if you are caching the contents of a table, i assume you are only ever replacing the set. i would suggest something like this:
    public class TableData<T>
      private final Set<T> _tableData;
      private final long _timestamp;
      public TableData(Set<T> data, long timestamp) {
        _tableData = Collections.unmodifiableSet(data);
        _timestamp = timestamp;
      // normal accessors here
    public class TableCache<T>
      private volatile TableData<T> _curTable;
      public void update(TableData<T> newTable)
        _curTable = newTable;
      public TableData<T> get()
        return _curTable;
    }the basic idea is that the TableData class is immutable (e.g. when you update the cache, you create a new set and new TableData instance), so you don't need to worry about concurrency issues (you can pass it a normal HashSet or whatever). thread visibility issues are resolved by using volatile on the TableCache class.
    Edited by: jtahlborn on Apr 17, 2010 10:47 AM

  • Thread safe RMI

    Thread safe RMI.
    My RMI server provides clients with the ability to CRUD data but in order to manage concurrency I did the following.
    1stly I would like to understand correctly the issues of RMI server objects....
    It is my understanding that RMI server can cater for eg 100 clients by spawning 100 threads at random for each client. This process is not managed (thread wise) and the result is that 20 clients wishing to update record A can do so at will? Various steps can be taken from what I gather...
    a) Synchronise (expensive)
    b) implement a lock manager.
    The step I have taken is include a lock manager and I have ensured that all locking an unlocking occur in a singleton server object that manages all sensitive data CRUD operations. Now I use a lock manager but I would like to know what happens if for eg the 1st RMI client dies and has its thread blocking
    all other threads from locking the same record? Does the thread die with the client or is there a counter measure for this? The obvious answer that comes to mind is Object.wait() inside the lock manager?
    The reason I ask was that because all of the locking occurs in a single method call in the Network
    Server's JVM, so is there a need to worry about the RMI connection dying during the middle the locking operation.
    Edited by: Yucca on May 23, 2009 8:14 PM/*
    * @(#)LockManager.java
    * Version 1.0.0
    * 27/03/2009
    import java.util.HashMap;
    import java.util.Map;
    import java.util.logging.Logger;
    import java.util.ResourceBundle;
    class LockManager {
         * The <code>Map</code> containing all the record number keys of currently
         * locked records that pair with the cookie value assigned to them when they
         * are initially locked.
        private static Map<Integer, Long> currentlyLockedMap =
                new HashMap<Integer, Long>();
        private static final Logger LOG = Logger.getLogger("project.db");
         * Locks a record so that it can only be updated or deleted by this client.
         * Returned value is a <code>long</code> that is the cookie value that must
         * be used when the record is unlocked, updated, or deleted.
         * If the specified record is already locked by a different client, then the
         * current thread gives up the CPU and consumes no CPU cycles until the
         * record is unlocked.
         * @param   recNo                   the assigned primary key of the record
         *                                  to be locked for an operation.
         * @param   data                    a <code>Data</code> instance used to
         *                                  check if the record exists before
         *                                  attempting the lock operation.
         * @return                          A <code>long</code> containing the
         *                                  cookie value that must be used when the
         *                                  record is unlocked.
         * @throws  RecordNotFoundException if specified record does not exist or if
         *                                  specified record is marked as deleted
         *                                  in the database file.
        long lock(int recNo, DB data) throws RecordNotFoundException {
            LOG.entering(this.getClass().getName(), "lock", recNo);
            synchronized (currentlyLockedMap) {
                try {
                    while (currentlyLockedMap.containsKey(recNo)
                            && currentlyLockedMap.get(recNo)
                            != Thread.currentThread().getId()) {
                        currentlyLockedMap.wait();
                    // Check if record exists.
                    data.read(recNo);
                    long cookie = Thread.currentThread().getId();
                    currentlyLockedMap.put(recNo, cookie);
                    LOG.fine("Thread " + Thread.currentThread().getName()
                            + "got Lock for " + recNo);
                    LOG.fine("Locked record count = " + currentlyLockedMap.size());
                    LOG.exiting(this.getClass().getName(), "lock", true);
                    return cookie;
                } catch (InterruptedException ie) {
                    throw new SystemException("Unable to lock", ie);
         * Releases the lock on a record. The cookie must be the cookie returned
         * when the record was locked.
         * @param   recNo                   the assigned primary key of the record
         *                                  to be unlocked after an operation.
         * @param   cookie                  the cookie returned when the record was
         *                                  locked.
         * @throws  RecordNotFoundException if specified record does not exist or if
         *                                  specified record is marked as deleted
         *                                  in the database file.
         * @throws  SecurityException       if the record is locked with a cookie
         *                                  other than cookie.
        void unlock(int recNo, long cookie) throws RecordNotFoundException,
                SecurityException {
            LOG.entering(this.getClass().getName(), "unlock",
                    new Object[] { recNo, cookie });
            synchronized (currentlyLockedMap) {
                checkLock(recNo, cookie);
                currentlyLockedMap.remove(recNo);
                LOG.fine("released lock for " + recNo);
                currentlyLockedMap.notifyAll();
            LOG.exiting(this.getClass().getName(), "unlock");
         * Checks if the given record is locked before doing any modification or
         * unlocking for the record.
         * <p/>
         * Checks the <code>Map</code> of record number keys and cookie values
         * to see if it contains the given record number.
         * @param   recNo                   the assigned primary key of the record
         *                                  to be checked if it is locked.
         * @param   lockCookie              the cookie returned when the record was
         *                                  initially locked.
         * @throws  SecurityException       if no lock exists for the record or if
         *                                  the record has been locked with a
         *                                  different cookie.
        void checkLock(int recNo, long lockCookie) throws SecurityException {
            LOG.entering(this.getClass().getName(), "checkLock",
                    new Object[] { recNo, lockCookie });
            // Check if record has been locked
            if (!currentlyLockedMap.containsKey(recNo)) {
                throw new SecurityException(ResourceBundle.getBundle(
                        "resources.ErrorMessageBundle").getString(
                        "lockNotAppliedKey"));
            // Check if record has been locked by different cookie.
            if (currentlyLockedMap.get(recNo) != lockCookie) {
                throw new SecurityException(ResourceBundle.getBundle(
                        "resources.ErrorMessageBundle").getString(
                        "notLockOwnerKey"));
            LOG.exiting(this.getClass().getName(), "checkLock");
    }Edited by: Yucca on May 23, 2009 8:16 PM
    Edited by: Yucca on May 23, 2009 8:18 PM

    It is my understanding that RMI server can cater for eg 100 clients by spawning 100 threads at random for each client.No. It spawns a new thread for every new connection. At the client end, RMI makes a new connection for every call unless it can find an idle connection to the same host that is less than 15 seconds old. So if the client is doing concurrent calls there will be concurrent threads at the server for that client.
    This process is not managed (thread wise)'Managed' meaning what?
    the result is that 20 clients wishing to update record A can do so at will?The result is that an RMI server is not thread safe unless you make it so.
    a) Synchronise (expensive)Compared to a database update the cost of synchronization is trivial.
    b) implement a lock manager. The database should already have one of those, and so does java.util.concurrent. Don't write your own. Personally I would just syncrhonize around the database calls.
    what happens if for eg the 1st RMI client dies and has its thread(a) the client doesn't have a thread, see above. The call has a thread.
    (b) at the server, the call will execute, regardless of the state of the client, until it is time to write the result back to the client, at which point the write will encounter an IOException of some description and the thread will exit.
    blocking all other threads from locking the same record?That can't happen unless you foul up your concurrency management.
    Does the thread die with the clientIt dies with the call.
    is there a need to worry about the RMI connection dying during the middle the locking operation.The server JVM won't notice until it is time to write the call result back, see above.

Maybe you are looking for