18

we have two threads accessing one list via a synchronized method. Can we

a) rely on the run time to make sure that each of them will receive access to the method based on the order they tried to or

b) does the VM follow any other rules

c) is there a better way to serialize the requests?

Cœur
  • 37,241
  • 25
  • 195
  • 267
MrG
  • 5,277
  • 17
  • 48
  • 66
  • 2
    It is fairly unlikely you really need this requirement. You may find that using ReentrantLock(true) is substantially slower than performing the whole operation with synchronized. – Peter Lawrey Nov 26 '09 at 21:29

7 Answers7

28

No, synchronized will give access in any order (Depends on the JVM implementation). This could even cause Threads to starve in some scenarios.

You can ensure the order by using ReentrantLock (since Java 5.0) with the fair=true option. (Lock lock = new ReentrantLock(true);)

Hardcoded
  • 6,476
  • 2
  • 22
  • 20
  • 7
    "synchronized will give access in random order (or who is the fastest to grab the Lock)". The order is simply not specified. It is almost certainly NOT random, and it is implementation dependent (and highly unlikely) that the "first" thread will always get the lock ... especially on a multiprocessor system. – Stephen C Nov 26 '09 at 10:39
  • 2
    You are right, Stephen. But you can't relay on a specific implementation, so the programmer must expect a random behaviour. – Hardcoded Nov 26 '09 at 11:20
  • 3
    The order isn't random nor is it guaranteed to be random. As soon a one thread blocks it can be context switched so it won't try again for a while so you can get one thread amongst many getting the lock many times before another thread gets a chance to wake up. – Peter Lawrey Nov 26 '09 at 21:32
  • 1
    Since the order depends on so many things outside of the scope of the programmer (Thread-Implementation, current workload of the CPU(s), number of the CPUs, etc), one could consider it "random" in a common sense, but definitly not in the statistical-proven-sense. Tried to clarify. – Hardcoded May 28 '15 at 12:22
  • 7
    ReentrantLock's docs says about fair=true that 'When set true, under contention, locks favor granting access to the longest-waiting thread' so setting that doesn't actually enforce strict ordering. – Paul Rubel Jan 06 '16 at 16:53
  • @PaulRubel So I guess there is no way to ensure the same order? – Harinder Jan 06 '16 at 16:57
  • @Harinder, at least not with ReentrantLock and in general no :( – Paul Rubel Jan 06 '16 at 21:29
12

No you cannot be sure that two calls to a synchronized method will occur in order. The order is unspecified and implementation dependent.

This is defined in the 17.1 Locks section of the JLS. Notice that is says nothing about the order in which threads waiting on a lock should gain access.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Like your answer, though saying nothing doesn't necessary imply that there will not be an order, so I guess it will depend on the implementation. And I guess HotSpot/OpenJDK rely on the OS thread scheduler. – user454322 May 25 '12 at 11:16
  • @user454322 - that's a fair assessment. – Stephen C May 26 '12 at 06:26
3

You can't rely on the order in which the particular method is called from each threads. If it is only two threads may be yes. But imagine if there are 3 threads and 1 thread already acquired access. The other 2 threads when they try to access will wait and any one of them can be awarded the access, and this does not depend on the order in which they called this method. So, it is not suggested to rely on the order.

Varun
  • 1,014
  • 8
  • 23
  • 3
    "So, it is not suggested to rely on the order." - That's an understatement!! I'd say that any program that does rely on it is *definitely* non-portable, and *probably* buggy on the platform it was implemented / tested on! – Stephen C Nov 26 '09 at 10:42
0

c) is there a better way to serialize the requests?

Are you by any chance using the list as a queue, i.e., does the usage pattern look something like this?

while (some condition) {
    synchronized(theList){
        anItem = get and remove an element from theList
    }
    do some work with anItem
}

If so, you may want to look at the BlockingQueue interface instead of using your own locking schemes. The implementations (like ArrayBlockingQueue) have settings for fairness and more.

gustafc
  • 28,465
  • 7
  • 73
  • 99
0

I always leave syncs to app server or engine unless defining own intensity

Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424
0

I have solved similar problem with couple of instrument. The problem I was trying to solve is Ping Pong Service. two thread one prints Ping and the other prints Pong. but They have to be SEQUENTIAL. (no double Ping or double Pong)

I will put one of the Implementation here but you can have a look other implementation (6 or 7 different way for now) https://github.com/tugrulkarakaya/pingpong

import java.util.concurrent.*;

public class Method2CyclicBarrier {

ExecutorService service;
CyclicBarrier c1 = new CyclicBarrier(2);
CyclicBarrier c2 = new CyclicBarrier(2);

public static void main(String[] args) {
    Method2CyclicBarrier m = new Method2CyclicBarrier();
    m.runPingPong();
}

public void runPingPong(){
    service = Executors.newFixedThreadPool(2);
        service.submit(() -> this.printPing(c1, c2));
        service.submit(() -> this.printPong(c1, c2));
}



public void printPing(CyclicBarrier c1, CyclicBarrier c2) {
    while(!Thread.currentThread().isInterrupted()) {
        try {
            c1.await();
            System.out.println("PING");
            c2.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        catch(BrokenBarrierException ex){

        }
    }
}

public void printPong(CyclicBarrier c1, CyclicBarrier c2){
    while(!Thread.currentThread().isInterrupted()) {
        try {
            c1.await();
            c2.await();
            System.out.println("PONG");
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        } catch(BrokenBarrierException ex){

        }
    }
}
}
-1

Yes.

If access to the list is via one synchronized method, concurrent requests from multiple threads will be serialized.

Conrad Meyer
  • 2,851
  • 21
  • 24
  • 2
    @Conrad. I don't think its true. When multiple threads are waiting for a monitor any one of them can be awarded depending on the implementation. We can't be sure that monitor will be awarded in the order the threads requested for it. – Varun Nov 26 '09 at 10:29
  • 5
    You are answering a subtly different question that what was asked. MrG is asking about the scheduling order of contested synchronized blocks, not whether synchronized blocks are obeyed. – Paul Wagland Nov 26 '09 at 10:31
  • Yeah, though I think it doesn't matter most of the time. – Conrad Meyer Nov 26 '09 at 11:20