15

What are the possible ways to make code thread-safe without using the synchronized keyword?

Malcolm
  • 41,014
  • 11
  • 68
  • 91
chhaya
  • 167
  • 1
  • 1
  • 6

7 Answers7

11

Actually, lots of ways:

  1. No need for synchronization at all if you don't have mutable state.
  2. No need for synchronization if the mutable state is confined to a single thread. This can be done by using local variables or java.lang.ThreadLocal.
  3. You can also use built-in synchronizers. java.util.concurrent.locks.ReentrantLock has the same functionality as the lock you access when using synchronized blocks and methods, and it is even more powerful.
Malcolm
  • 41,014
  • 11
  • 68
  • 91
  • 1
    I prefer (2), but I'm not sure if its' possible to implement message-passing without using the 'synchronized' keyword. Can I make a producer-consumer queue without 'synchronized'? – Martin James Apr 26 '12 at 10:07
  • 1
    @MartinJames Any of the Concurrent classes like Queues and Exchangers can be used without synchronization. (They use Lock instead) The Disrupter supports messaging without locks or synchronization. (I have a library which does this as well) – Peter Lawrey Apr 26 '12 at 11:27
  • @PeterLawrey - so, thread-safe code without the 'synchronized' keyword is certainly possible and, in fact practical. Now, all that remains is to get developers to stop using Thread.join() and we're done :) – Martin James Apr 26 '12 at 11:43
  • @MartinJames It is better to say that thread-safe code is possible without *locking*. Sometimes you can avoid using locking completely (intrinsic locks or not, doesn't matter), and then everything becomes much easier. However, if you get to locking, it is better to use `synchronized` than extrinsic locks if you don't need advanced features. The notaion of intrinsic locks is concise, and the code doesn't need to contain try-finally blocks (therefore much safer). – Malcolm Apr 26 '12 at 12:29
6

Only have variables/references local to methods. Or ensure that any instance variables are immutable.

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
4

You can make your code thread-safe by making all the data immutable, if there is no mutability, everything is thread-safe.

Secondly, you may want to have a look at java concurrent API which has provision for providing read / write locks which perform better in case there are lots of readers and a few writers. Pure synchronized keyword will block two readers also.

Kalpak Gadre
  • 6,285
  • 2
  • 24
  • 30
4
   ////////////FIRST METHOD USING SINGLE boolean//////////////


    public class ThreadTest implements Runnable { 
        ThreadTest() {
            Log.i("Ayaz", "Constructor..");
        }

        private boolean lockBoolean = false;

        public void run() {
            Log.i("Ayaz", "Thread started.." + Thread.currentThread().getName());
            while (lockBoolean) {
             // infinite loop for other thread if one is accessing
            }
            lockBoolean = true;
            synchronizedMethod();
        }

        /**
         * This method is synchronized without using synchronized keyword
         */
        public void synchronizedMethod() {
            Log.e("Ayaz", "processing...." + Thread.currentThread().getName());
            try {
                Thread.currentThread().sleep(3000);
            } catch (Exception e) {
                System.out.println("Exp");
            }
            Log.e("Ayaz", "complete.." + Thread.currentThread().getName());
            lockBoolean = false;
        }

    } //end of ThreadTest class

     //For testing use below line in main method or in Activity
     ThreadTest threadTest = new ThreadTest();
            Thread threadA = new Thread(threadTest, "A thead");
            Thread threadB = new Thread(threadTest, "B thead");
            threadA.start();
            threadB.start();

///////////SECOND METHOD USING TWO boolean/////////////////



 public class ThreadTest implements Runnable {
    ThreadTest() {
        Log.i("Ayaz", "Constructor..");
    }

    private boolean isAnyThreadInUse = false;
    private boolean lockBoolean = false;

    public void run() {
        Log.i("Ayaz", "Thread started.." + Thread.currentThread().getName());
        while (!lockBoolean)
            if (!isAnyThreadInUse) {
                isAnyThreadInUse = true;
                synchronizedMethod();
                lockBoolean = true;
            }
    }

    /**
     * This method is synchronized without using synchronized keyword
     */
    public void synchronizedMethod() {
        Log.e("Ayaz", "processing...." + Thread.currentThread().getName());
        try {
            Thread.currentThread().sleep(3000);
        } catch (Exception e) {
            System.out.println("Exp");
        }
        Log.e("Ayaz", "complete.." + Thread.currentThread().getName());
        isAnyThreadInUse = false;
    }

} // end of ThreadTest class

     //For testing use below line in main method or in Activity
     ThreadTest threadTest = new ThreadTest();
     Thread t1 = new Thread(threadTest, "a thead");
     Thread t2 = new Thread(threadTest, "b thead");
     t1.start();
     t2.start();
Ayaz Ahmad
  • 151
  • 1
  • 5
2

To maintain predictability you must either ensure all access to mutable data is made sequentially or handle the issues caused by parallel access.

The most gross protection uses the synchronized keyword. Beyond that there are at least two layers of possibility, each with their benefits.

Locks/Semaphores

These can be very effective. For example, if you have a structure that is read by many threads but only updated by one you may find a ReadWriteLock useful.

Locks can be much more efficient if you choose your lock to match the algorithm.

Atomics

Use of AtomicReference for example can often provide completely lock free functionality. This can usually provide huge benefits.

The reasoning behind atomics is to allow them to fail but to tell you they failed in a way you can handle it.

For example, if you want to change a value you can read it and then write its new value so long as it is still the old value. This is called a "compare and set" or cas and can usually be implemented in hardware and so is extremely efficient. All you then need is something like:

long old = atomic.get();
while ( !atomic.cas(old, old+1) ) {
  // The value changed between my get and the cas. Get it again.
  old = atomic.get();
}

Note, however, that predictability is not always the requirement.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
0

Well there are many ways you can achieve this, but each contains many flavors. Java 8 also ships with new concurrency features. Some ways you could make sure thread safety are:
Semaphores
Locks-Reentrantlock,ReadWriteLock,StampedLock(Java 8)

-2

Why do u need to do it?

Using only local variable/references will not solve most of the complex business needs. Also, if instance variable are immutable, their references can still be changed by other threads.

One option is use something like a SingleThreadModel, but it is highly discouraged and deprecated.

u can also look at concurrent api as suggested above by Kal

Kshitij
  • 8,474
  • 2
  • 26
  • 34
  • "if instance variable are immutable, their references can still be changed" no they can't – NimChimpsky Apr 26 '12 at 10:03
  • can u explain that. How i see it is if i have a instanace variable String s ="xyz", My thread1 can change the reference of it to s="abc"; and thread2 will now get s="abc" – Kshitij Apr 26 '12 at 10:08
  • s is a reference, it has changed, its not immutable you would need "final string s" – NimChimpsky Apr 26 '12 at 10:11
  • http://stackoverflow.com/questions/1568722/on-the-thread-safety-of-instance-variable-initialization – NimChimpsky Apr 26 '12 at 10:17
  • "final String s" will not solve the purpose here as it will just act as a constant. – Kshitij Apr 26 '12 at 10:18
  • 1
    with string s your s reference is not immutable it can reference a different string, just by doing s = "yourarewrong". You say immutable instance variables are not thread safe, and then give an example of a mutable instance variable. – NimChimpsky Apr 26 '12 at 10:21
  • that's what i am asking you. "show me an example of immutable instance variable". – Kshitij Apr 26 '12 at 10:26
  • as per my understanding, there's nothing like immutable instance variable – Kshitij Apr 26 '12 at 10:27
  • I just did. What do you think the word final does ? – NimChimpsky Apr 26 '12 at 10:28
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/10541/discussion-between-kshitij-and-nimchimpsky) – Kshitij Apr 26 '12 at 10:31