class Untitled {
public static void main(String[] args) {
MyRunnable r1 = new MyRunnable();
Thread t1 = new Thread(r1,"Thread 1:");
Thread t2 = new Thread(r1,"Thread 2:");
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable
{
String s1 = "Hello World";
String s2 = "Hello New World";
public void run()
{
synchronized(s1)
{
for(int i =0;i<3;++i)
System.out.println(Thread.currentThread().getName()+s1);
}
synchronized(s2)
{
for(int i = 0;i<3;++i)
System.out.println(Thread.currentThread().getName()+s2);
}
}
}
OUTPUT:
Thread 1:Hello World
Thread 1:Hello World
Thread 1:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 2:Hello New World
Thread 2:Hello New World
Thread 2:Hello New World
Why can't Thread2 execute the second synchronized block in the run() method when Thread1 is executing the first synchronized block even though lock objects are different.Does Thread2's execution wait at the first synchronized block till Thread1 leaves that block??
If so how to make both synchronized blocks run concurrently??
Does Thread2's execution wait at the first synchronized block till Thread1 leaves that block??
Yes that's the idea - thread2 executes the blocks one after the other. If it is blocked and can't enter the first one, it will wait there until the s1 lock becomes available.
If so how to make both synchronized blocks run concurrently??
You would need to split them in two different runnables and use one thread for each.
Because within the run method statements are executed in sequentially not parallely.
So who ever Thread 1 or Thread 2 acquire the lock of s1 other will wait untill it is released.
The two blocks are one after the other, which means that Thread 2 has to go though block 1 before going through block 2
Why can't Thread2 execute the second synchronized block in the run()
method when Thread1 is executing the first synchronized block
Code is executed line by line, The execution doesnt jump to next block and Thread 2 waits for Thread 1 to leave the 1st Synchronized block.
Does Thread2's execution wait at the first synchronized block till
Thread1 leaves that block
Yes.
If so how to make both synchronized blocks run concurrently??
So keep them In seperate Runnable Instances. and Not one after the other in a Sequence.
It is simply the compiler execute the code i.e. compiler execute code in sequence the way they are written. thread 2 cannot skip first block of code. it will first execute first block then others.
Here's an example of getting them both to run concurrently. Note that not only have I put each loop in a separate thread but I have reduced the scope of the synchronization to just the print.
public class Test {
static class MyRunnable implements Runnable {
final String s1 = " Hello World - ";
final String s2 = " Hello New World - ";
static final int n = 10;
#Override
public void run() {
// Two loops in two threads.
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < n; ++i) {
// Scope reduced.
synchronized (s1) {
System.out.println(Thread.currentThread().getName() + s1 + i);
}
}
}
}, Thread.currentThread().getName() + "(a)").start();
// Two loops in two threads.
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < n; ++i) {
// Scope reduced.
synchronized (s2) {
System.out.println(Thread.currentThread().getName() + s2 + i);
}
}
}
}, Thread.currentThread().getName() + "(b)").start();
}
}
public void test() {
MyRunnable r1 = new MyRunnable();
Thread t1 = new Thread(r1, "Thread 1:");
Thread t2 = new Thread(r1, "Thread 2:");
t1.start();
t2.start();
}
public static void main(String args[]) {
new Test().test();
}
}
class ThreadExample {
public static void main(String[] args) {
MyRunnable15756 r1 = new MyRunnable15756();
Thread t1 = new Thread(r1,"Thread 1:");
Thread t2 = new Thread(r1,"Thread 2:");
t1.start();
t2.start();
}
}
class MyRunnable15756 implements Runnable
{
String s1 = "Hello World";
String s2 = "Hello New World";
Runnable runnable1 = new Runnable(){
#Override
public void run() {
synchronized(s1)
{
for(int i =0;i<30;++i)
System.out.println(Thread.currentThread().getName()+s1);
}
}
};
Runnable runnable2 = new Runnable(){
#Override
public void run() {
synchronized(s2)
{
for(int i = 0;i<30;++i)
System.out.println(Thread.currentThread().getName()+s2);
}
}
};
public void run()
{
new Thread(runnable1).start();
new Thread(runnable2).start();
}
}
Related
I have the following kind of code:
synchronized block1 {
//only one thread in the block
}
{lot of code where synchronization not necessary}
synchronized block2 {
//only one thread in the block.
//All the threads that executed block1 before this thread should have already executed this block.
}
Each thread first executes block1, non synchronized block, and block2 in that same order.
If thread T1 executes block1 before thread T2, then T1 should execute block2 before T2. There are more than two threads.
Is there a way to achieve this in java?
As I understand Critical Section #2 MUST be executed in the same order as Critical Section #1
If thread T1 executes block1 before thread T2, then T1 should execute block2 before T2. There are more than two threads.
Then a Queue might be used to ensure the order of execution.
private Object lock = new Object();
private Queue<Thread> threadQueue = new ArrayDeque<>();
// https://stackoverflow.com/questions/32353283/synchronization-threads-execute-two-critical-sections-in-same-order
public void executeCriticalSectionsInOrder() throws InterruptedException {
// Critical Section #1
synchronized (lock){
// synchronized code #1
// Add self to queue
threadQueue.add(Thread.currentThread());
}
// {lot of code where synchronization not necessary}
// Critical Section #2
synchronized (lock) {
//All the threads that executed block1 before this thread should have already executed this block.
// Wait turn
Thread t = threadQueue.element(); // Do not remove until it is self
while (t != Thread.currentThread()) {
lock.wait();
// After sleep try again
t = threadQueue.element();
}
// Verified own turn. Update status
threadQueue.remove();
// synchronized code #2
lock.notifyAll(); // Awake any waiting thread after exiting section.
}
However If one thread dies/exits without removing itself from the queue, then following threads will be blocked indefinetely. Maybe add a finally block to do the housekeeping?
Note: In Nicholas Robinson's answer a position order was suggested instead of a queue, which seems slightly more efficient.
This basically creates a queue that threads will wait in until their number comes up. [UPDATED]
private AtomicInteger place = new AtomicInteger(0);
private AtomicInteger currentPlaceInQueue = new AtomicInteger(0);
private ReentrantLock lock = new ReentrantLock();
private Condition notNext = lock.newCondition();
public void method() {
ThreadLocal position = new ThreadLocal();
synchronized(this) {
//Your code
position.set(place.getAndIncrement());
}
// More code
lock.lock();
while ((int) currentPlaceInQueue.get() != position.get()) {
notNext.await();
}
// More code
lock.unlock();
currentPlaceInQueue.getAndIncrement();
notNext.notifyAll();
}
The synchronized blocks in your example are a red herring. Your problem is, you have N threads, and you have two blocks of code, and you want to make sure that none of the threads enters the second block until all of them have finished the first block.
You use a CyclicBarrier for that. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html
You should be able to use a Lock which you take before calling block1 and release after calling block2.
static Lock lock = new ReentrantLock();
Random random = new Random();
public void block1() throws InterruptedException {
System.out.println("Enter block 1");
Thread.sleep(random.nextInt(500));
System.out.println("Leave block 1");
}
public void block2() throws InterruptedException {
System.out.println("Enter block 2");
Thread.sleep(random.nextInt(500));
System.out.println("Leave block 2");
}
private class BlockTester implements Runnable {
long start = System.currentTimeMillis();
#Override
public void run() {
while (System.currentTimeMillis() < start + 10000) {
lock.lock();
try {
System.out.println("Thread: " + Thread.currentThread().getName());
block1();
block2();
} catch (InterruptedException ex) {
System.out.println("Interrupted");
} finally {
lock.unlock();
}
}
}
}
public void test() throws InterruptedException {
Thread[] blockTesters = {
new Thread(new BlockTester()),
new Thread(new BlockTester()),
new Thread(new BlockTester()),
new Thread(new BlockTester()),
new Thread(new BlockTester())
};
for (Thread t : blockTesters) {
t.start();
}
for (Thread t : blockTesters) {
t.join();
}
}
For this below program, the ans is --> print : printName , then wait for 5 seconds then print : printValue
But as far as I know that its up to JVM to pick a thread and start its run method. So why it cannot be (printvalue printname and then 5 sec pause).
Note : I understand the conept of synchornized method but how we are sure here that JVM will always pick the thread t1 as its first thread.
class B {
public synchronized void printName() {
try {
System.out.println("printName");
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
}
}
public synchronized void printValue() {
System.out.println("printValue");
}
}
public class Test1 extends Thread {
B b = new B();
public static void main(String argv[]) throws Exception {
Test1 t = new Test1();
Thread t1 = new Thread(t, "t1");
Thread t2 = new Thread(t, "t2");
t1.start();
t2.start();
}
public void run() {
if (Thread.currentThread().getName().equals("t1")) {
b.printName();
} else {
b.printValue();
}
}
}
In this context, the synchronize just means that they can't run at the same time, not that they have to run in order. If you want them to run in order, then you don't want threads, or you want a more sophisticated queuing mechanism.
So, you are correct in that the it could either be "printName" pause "printValue" or "printValue" "printName" pause.
If you run the program multiple times, you'll likely see the first one more frequently. You will see the second output occasionally. The skew is because there is a slight delay between the start() on thread 1 and start() on thread 2.
how we are sure here that JVM will always pick the thread t1 as its first thread.
You can never be sure that the t1 thread will start running before the t2 thread starts running. If you need the t1 thread to do something before the t2 thread does some other thing, then you will have to use some synchronization object (e.g., a Semaphore) to make t2 wait.
Semaphore semaphore = new Semaphore(0);
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
doTheThingThatHasToBeDoneFirst();
semaphore.release();
doOtherStuff();
}
}).start();
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
semaphore.acquire(); //will not return until t1 thread calls release().
doOtherOtherStuff();
}
}).start();
But that is not really a smart way to use threads. Why not just do this instead?
doTheThingThatHasToBeDoneFirst();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
doOtherStuff();
}
}).start();
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
doOtherOtherStuff();
}
}).start();
As a rule of thumb, the more synchronization you have between your threads, the less benefit you get from using threads. If you want certain things to happen in a certain order, you should do those things in that order in a single thread.
The trick to using threads is to design your program so that there are useful things it can do where order does not matter.
I am expecting below to increment c value to be 2. But I am always getting 1 output even after the 2nd thread started.
package test.main;
public class TestThread implements Runnable {
private int c=0;
#Override
public void run() {
synchronized(this){
c=c+1;
//wait(1000);
go();
}
}
private void go() {
System.out.println("Thread name :"+Thread.currentThread()+" in go() : "+c);
}
public static void main(String[] args) throws InterruptedException {
System.out.println("main()");
Thread t1 = new Thread(new TestThread(),"thread1");
Thread t2 = new Thread(new TestThread(),"thread2");
t1.start();
t2.start();
}
}
In thread t1 and t2 you are passing two completely different objects. So in both cases it is incrementing their own c which are not related to each other.
Use a single object
TestThread tt = new TestThread();
Thread t1 = new Thread(tt,"thread1");
Thread t2 = new Thread(tt,"thread2");
You have created two thread objects.
Thread t1 = new Thread(new TestThread(),"thread1");
Thread t2 = new Thread(new TestThread(),"thread2");
And each thread object has its own copy of c as its not class level variable. Its instance variable.
So, it will not give you a value 2
Each TestThread object has its own copy of c, so each will be incremented only once.
Thread t1 = new Thread(new TestThread(),"thread1");
Thread t2 = new Thread(new TestThread(),"thread2");
You are creating two different instances of TestThread and
private int c=0;
is an instance variable(not a class variable). So it is expected for c to be 1 after run() is executed for each Thread.
I have a two part question...
I have a class with a function in it that can only be accessed by any one thread at a given time. Making this a synchronized function or a synchronized block still allows for multiple threads since different threads are accessing it within the class. How can I make sure only one thread accesses this code? (See code example below)
With the synchronized function, the calls to the function are queued up. Is there any way to only allow the last call to the function to access the code? So if I have Thread1 currently accessing my function, then Thread2 and Thread3 try to access it (in that order) only Thread3 will be given access once Thread1 is complete.
public void doATask() {
// I create a new thread so the interface is not blocked
new Thread(new Runnable() {
#Override
public void run() {
doBackgroundTask();
}
}).start();
}
private void doBackgroundTask(MyObject obj) {
// perform long task here that is only being run by one thread
// and also only accepts the last queued thread
}
Thanks for any help!
If the second thread in your example can just return, you could use a combination of a lock and keeping track of the last thread executing the method. It could look like this:
private volatile Thread lastThread;
private final ReentrantLock lock = new ReentrantLock();
private void doBackgroundTask(Object obj) throws InterruptedException {
Thread currentThread = Thread.currentThread();
lastThread = currentThread;
try {
// wait until lock available
lock.lockInterruptibly();
// if a thread has arrived in the meantime, exit and release the lock
if (lastThread != currentThread) return;
// otherwise
// perform long task here that is only being run by one thread
// and also only accepts the last queued thread
} finally {
lock.unlock();
}
}
Full working test with additional logging that shows the thread interleaving and that T2 exits without doing nothing:
class Test {
private volatile Thread lastThread;
private final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) throws Exception {
final Test instance = new Test();
Runnable r = new Runnable() {
#Override
public void run() {
try {
instance.doBackgroundTask(null);
} catch (InterruptedException ignore) {}
}
};
Thread t1 = new Thread(r, "T1");
Thread t2 = new Thread(r, "T2");
Thread t3 = new Thread(r, "T3");
t1.start();
Thread.sleep(100);
t2.start();
Thread.sleep(100);
t3.start();
}
private void doBackgroundTask(Object obj) throws InterruptedException {
Thread currentThread = Thread.currentThread();
System.out.println("[" + currentThread.getName() + "] entering");
lastThread = currentThread;
try {
// wait until lock available
lock.lockInterruptibly();
// if a thread has arrived in the meantime, exit and release the lock
if (lastThread != currentThread) return;
// otherwise
// perform long task here that is only being run by one thread
// and also only accepts the last queued thread
System.out.println("[" + currentThread.getName() + "] Thinking deeply");
Thread.sleep(1000);
System.out.println("[" + currentThread.getName() + "] I'm done");
} finally {
lock.unlock();
System.out.println("[" + currentThread.getName() + "] exiting");
}
}
}
Output:
[T1] entering
[T1] Thinking deeply
[T2] entering
[T3] entering
[T1] I'm done
[T1] exiting
[T2] exiting
[T3] Thinking deeply
[T3] I'm done
[T3] exiting
What you want is probably a worker thread that waits for a signal to do some work. doATask() simply sends a signal to trigger the work. Accumulative signals are equivalent to one signal.
final Object lock = new Object();
MyObject param = null;
public void doATask(arg)
synchronized(lock)
param=arg;
lock.notify();
MyObject awaitTask()
synchronized(lock)
while(param==null)
lock.wait();
tmp=param;
param=null;
return tmp;
// worker thread
public void run()
while(true)
arg = awaitTask();
doBackgroundTask(arg);
I want to restart a thread for some use, for example in the below code.
class Ex13 implements Runnable {
int i = 0;
public void run() {
System.out.println("Running " + ++i);
}
public static void main(String[] args) throws Exception {
Thread th1 = new Thread(new Ex13(), "th1");
th1.start();
//th1.join()
Thread th2 = new Thread(th1);
th2.start();
}
}
When I'm executing the above program , some time i'm getting the output as
Running 1
Running 2
and some time i'm getting only
Running 1
After few run i'm getting only
Running 1 as output.
I'm totally surprise about this behavior. Can any one help me understand this.
if I put the join() then i'm getting only Running 1.
You reuse Thread instance, not Runnable. Thread overwrites its run() method to
public void run() {
if (target != null) {
target.run();
}
}
Where target is the Runnable that you give to the constructor. besides that, Thread has an exit() method that is called by the VM, and this method sets target to null (the reason is this bug). So if your first thread has the chance to finish its execution, its run() method is pretty much empty. Adding th1.join() proves it.
If you want to keep some state, you need to keep reference to your Runnable instance, not the Thread. This way run() method will not be altered.
I don't know why do you need this, but (please note that this code doesn't ensure that th1 is ALWAYS executed before th2, though) :
public static class Ex13 implements Runnable {
AtomicInteger i = new AtomicInteger(0);
CountDownLatch latch;
Ex13(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("Running " + i.incrementAndGet());
latch.countDown();
}
}
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(2);
Ex13 r = new Ex13(latch);
Thread th1 = new Thread(r, "th1");
th1.start();
Thread th2 = new Thread(r);
th2.start();
latch.await(); // wait until both theads are executed
System.out.println("Done");
}
You want the incrementing of i to be synchronized, i.e.
public class Ex13 implements Runnable {
int i=0;
public void run() {
System.out.println("Running "+ increment());
}
private synchronized int increment() {
return ++i;
}
}
The Java Tutorial has a very nice explanation of this given a very similar scenario. The problem is that incrementing a variable is not an atomic operation. Each thread needs to read the current state of i before setting it to the new value. Restricting access to incrementing the variable to one thread at a time assures you will get consistent behavior.
To see whats happening in the System.out.println you can also print the thread name:
Thread t = Thread.currentThread();
String name = t.getName();
System.out.println("name=" + name);
I see you call the two threads with the same runnable object, so they will both use the same "i" variable, in order for you to get Running 1 Running 2 you need to synchronize "i"