If I bind thread A to CPU1 using Affinity, and thread B to CPU2, and thread A modifies variable C in a synchronized method in the runnable, and thread B reads the variable in a non-synchronized method, will thread B get the correct value?
When a thread releases a lock, it flushes the shared variables in its working memory to the main memory, and at the same time makes the shared variables in the working memory of other threads invalid. This means that other threads must re-fetch these variables from the main memory when accessing them. I tried to create a deadlock effect by adding an infinite loop in thread A's synchronized method, but thread B still gets the correct value. Why is this happening?
public class SyncTest {
public static void main(String[] args)throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(counter, "A");
Thread thread2 = new Thread(counter, "B");
thread1.start();
thread2.start();
thread2.join();
thread1.join();
}
}
class Counter implements Runnable{
private int count;
public Counter() {
count = 0;
}
//synchronized Code Block
public void countAdd() {
try (AffinityLock affinityLock = AffinityLock.acquireLock(1)) {
// do some work while locked to a CPU.
synchronized(Counter.class) {
count = count +1 ;
System.out.println(Thread.currentThread().getName() + ":" + count);
while(true){}
}
}
}
//Non-synchronized Code Block
public void printCount() {
try (AffinityLock affinityLock = AffinityLock.acquireLock(2)) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + " count:" + count);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
#Override
public void run() {
String threadName = Thread.currentThread().getName();
if (threadName.equals("A")) {
countAdd();
} else if (threadName.equals("B")) {
printCount();
}
}
}
Related
public class MyVisibility {
private static int count = 0;
private static Object lock = new Object();
public static void main(String[] args) {
new MyVisibility.thread1().start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
new MyVisibility.thread2().start();
}
static class thread1 extends Thread {
int i = 0;
#Override
public void run() {
super.run();
while (true) {
synchronized (lock) {
count++;
System.out.println("Thread one count is " + count);
try {
lock.wait();
System.out.println("i am notified");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count > 5) {
return;
}
}
}
}
static class thread2 extends Thread {
int i = 10;
#Override
public void run() {
super.run();
while (true) {
synchronized (lock) {
count++;
System.out.println("Thead 2 count is " + count);
lock.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count > 10) {
return;
}
}
}
}
}
In above code,
Current result on execution : I can see lock.notify() is getting called only after end of the while loop.
My assumption is Since lock.notify() is getting called immediately after count variable getting incremented, and immediately it should notify the waiting thread to resume its execution, instead after second thread completion of execution call is going for waiting thread to resume, what is the reason for this, can someone correct me what was wrong with my understanding.
Thank you.
Your deduction - "I can see lock.notify() is getting called only after end of the while loop" is not entirely correct. Try running multiple times, or put break point just after synchronized block of thread2, and then you will see thread1 "i am notified" being printed.
From documentation of notify() -
The awakened thread will not be able to proceed until the current
thread relinquishes the lock on this object
In your case before thread2 relinquishes lock and then thread1 acquires lock, thread2 acquires lock again by going into synchronized block.
I have the following class
public class OddPrinter implements Runnable {
public void run() {
try {
for (int n = 0; n <= 10; n++) {
if((n%2) != 0)
System.out.println(" Odd Thread" + n);
Thread.sleep(1000);
}
System.out.println("Exiting Odd Thread");
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
And the main class which tries to have a synchronized access to the object of the above class
public class MultiThread {
public static void main(String[] args) {
Thread t1, t2;
OddPrinter first = new OddPrinter();
synchronized(first)
{
t1 = new Thread(first, "firstThread");
t1.start();
t2 = new Thread(first, "secondThread");
t2.start();
}
}
}
I am getting an output as follows
Odd Thread1
Odd Thread1
Odd Thread3
Odd Thread3
Odd Thread5
Odd Thread5
Odd Thread7
Odd Thread7
Odd Thread9
Odd Thread9
Exiting Odd Thread
Exiting Odd Thread
A synchronized block ensures
that a call to a method that is a member of object occurs only after the current thread has
successfully entered object’s monitor.
According to the above reference ( Java2 - The Complete Reference - Herbert Schildt), I am expecting an output where one thread waits for the other to finish the printing of the odd numbers. But that is not happening. What is the issue here?
A synchronized block ensures that a call to a method that is a member of object occurs only after the current thread has successfully entered object’s monitor.
No it doesn't. It ensures that a synchronized method that is an instance member of the class of the object occurs only after the current thread has exited the block, if invoked on the same object, and that another synchronized block on the same object doesn't execute until this block exits.
Several of those conditions don't apply to your code.
I am expecting an output where one thread waits for the other to finish the printing of the odd numbers.
Wait for thread t1 to complete before starting thread t2:
t1.start():
t1.join();
t2.start();
You only synchronized one access. The other threads don't synchronize on the object, so nothing is blocked. Even if they did and were, once both threads have started, the code block in main completes and the threads are free to run anyway.
Furthermore, the synchronization you used in main happens in advance of any other threads that might conflict, and the main thread doesn't need any shared state in the first place, so the synchronization there is useless.
Study the concepts "critical section", "memory barrier", and Java's "happens-before". Buy and study the book Java Concurrency in Practice, by Brian Goetz, et al.
synchronized lock should be put inside your runnable code, not your main method.
I think you can either put synchronize to your method
public class OddPrinter implements Runnable {
public synchronized void run() {
try {
for (int n = 0; n <= 10; n++) {
if((n%2) != 0)
System.out.println(" Odd Thread" + n);
Thread.sleep(1000);
}
System.out.println("Exiting Odd Thread");
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
Or, you can put it in your method like this
public class OddPrinter implements Runnable {
static Object lock;
public void run() {
synchronized (lock) {
try {
for (int n = 0; n <= 10; n++) {
if((n%2) != 0)
System.out.println(" Odd Thread" + n);
Thread.sleep(1000);
}
System.out.println("Exiting Odd Thread");
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
You need to change OddPrinter where you can put synchronized block and use a single lock to synchronized so at time one thread can enter to critical section.And remove the synchronized block from main method.
public class OddPrinter implements Runnable {
private Object lock;
public OddPrinter(Object lock) {
this.lock = lock;
}
public void run() {
synchronized (lock) {
for (int n = 0; n <= 10; n++) {
if ((n % 2) != 0)
System.out.println(" Odd Thread" + n);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Exiting Odd Thread");
}
}
}
public class MultiThread {
public static void main(String[] args) {
Thread t1, t2;
Object object=new Object();
t1 =new Thread(new OddPrinter(object),"firstThread");
t1.start();
t2 =new Thread(new OddPrinter(object),"secondThread");
t2.start();
}
}
This is definitely not the way synchronization should be implemented. In your implementation there is no monitor/locks or notify implementation since the lock acquired is soon out of scope of main thread's control.
It's completely wrong to do this way. In case you wanted to do something exclusive, the lock should be locked inside your thread -- not outside!.
public class MyThread implements Runnable {
private Object mutex;
public MyThread(Object sharedObject) {
this.mutex = sharedObject;
}
public void run() {
// Method 1 -- Class reference used as the mutex: locks and executes only one instance between the blocks
synchronized (MyThread.class) {
}
// Method 2 -- All the same instance of the object reference used as mutex receives a blocked interference, and only one thread is executed.
synchronized (mutex) {
}
}
// Method 3 - Only one synchronized method inside the class is executed at any given point in time.
private synchronized void produce() {
}
// Method 3 (Contd.) - Added in conjunction with produce() call
private synchronized void consume() {
}
}
I want to make a test, two thread, one thread is changing the value, another thread use a while to wait the first thread, and then break and finish.But the question is the waiting thread is always running, can' stop any more. Another question is when i open the code of "System.out.println(i + " run");", all the thread can work normally, it's so strange.
import java.util.Date;
public class ThreadTestTwo {
public int a = 0, b = 0,c = 0;
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
while (true) {
if(c == 1){
b = a;
// System.out.println(i+", set b "+a);
break;
}
// System.out.println(i + " run");
}
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
try {
writeThread.join();
readThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i+" end");
if(b != 1)
throw new RuntimeException("b = "+b);
}
}
The writes of one thread are NOT guaranteed to be seen for another thread unless the variables are marked as volatile or otherwise the transactions need to handled using synchronization or explicit locking
In your case, a,b,c are the instance variables accessed by multiple threads and the reader thread caches the values and so it doesn't see the writer thread's flushed value.
Please refer the below link for more details:
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
I advise you to read more on Threads. Here it is an interesting document from O'really: http://chimera.labs.oreilly.com/books/1234000001805/ch09.html
As for your implementation, you should be aware that the modification of one variable by a thread may not be seen by a reader thread. To combat that either use synchronised gets and sets, access the variables inside a synchronized block, or use an AtomicReference. You could also use a Lock such as ReantrantLock.
Also, if you have two threads, in which the first is waiting for the input of the second, you could use the wait() inside a synchronized block for the first, so that the second could notify() the first one when it finishes its job.
Something like this:
import java.util.Date;
public class ThreadTestTwo {
private int a = 0, b = 0,c = 0;
private final Object lock = new Object();
//Any object is good as a lock, and for a simple case as this it's fine.
//This object will work as a monitor for the synchronized blocks.
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
try {
while( c != 1 ) {
lock.wait();
}
}
catch ( InterruptedException ex ) {
//Exception handling
}
b = a;
}
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
a = 1;
c = 1;
lock.notify();
}
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
System.out.println(i+" end");
}
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
}
I would say you don't need join() with this method. But if want to wait for the second thread to start after the first is finished, you have to use join() before starting it. Like this:
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
But if you use join(), for this particular case, I would say you wouldn't need any synchronized blocks or conditions, since the second thread would only start after the death of the first one. Something like this:
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
b = a;
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
System.out.println(i+" end");
}
I hope I have helped.
Have a nice day. :)
It's not a good idea to use an simple int as a signal between threads because it's not thread safe.
So try to use AtomicInteger instead or make your int volatile and see what will happen.
First of all, this is not a homework.
I have written a piece of code so that:
Thread-1 prints 1,4,7,... (diff is 3)
Thread-2 prints 2,5,8,...
Thread-3 prints 3,6,9,...
And the final output should be:
1,2,3,4,5,6,7,8,9,...
Here's the code that works wonderfully well:
package threadAlgo;
public class ControlOrder {
volatile Monitor monitor = new Monitor();
public static void main(String[] args) {
ControlOrder order = new ControlOrder();
Thread one = new Thread(new Task(order.monitor, 1));
one.setName("Thread-1");
Thread two = new Thread(new Task(order.monitor, 2));
two.setName("Thread-2");
Thread three = new Thread(new Task(order.monitor, 3));
three.setName("Thread-3");
one.start();
two.start();
three.start();
}
}
class Monitor {
int threadNumber = 1;
}
class Task implements Runnable {
private Monitor monitor;
private int myThreadNumber;
private int currentCount;
Task(Monitor monitor, int myThreadNumber) {
this.monitor = monitor;
this.myThreadNumber = myThreadNumber;
this.currentCount = myThreadNumber;
}
#Override
public void run() {
while (true) {
while (monitor.threadNumber != myThreadNumber) {
synchronized (monitor) {
try {
monitor.wait(100); //DOESN'T WORK WITHOUT THE TIMEOUT!!!
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (monitor) {
if (monitor.threadNumber == myThreadNumber) {
System.out.println(Thread.currentThread().getName() + ": " + currentCount);
currentCount = currentCount + 3;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (myThreadNumber == 3) {
monitor.threadNumber = 1;
} else {
monitor.threadNumber = myThreadNumber + 1;
}
monitor.notifyAll();
}
}
}
}
The only problem is that if I use wait() instead of wait(timeout), then the thread halts.
UPDATE:
Wait condition (while loop) should be inside synchronized block. A lesson for beginners, including me.
You should always
perform notifyAll/notify in conjunction with a change in state.
check the state change before using wait() in a loop.
If you call notify() and no wait() is waiting, then the signal is lost, so unless you check a state change, (or timeout) you can block forever waiting for a signal which doesn't change.
here is my class
public class ThreadTest {
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
threadTest.m1();
synchronized (threadTest) {
threadTest.m2();
}
System.out.println("End of main thread");
}
public void m1() {
Thread myThread = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
}
System.out.println("end of mythread");
}
});
myThread.start();
}
public void m2() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
}
}
}
Although i put my code inside synchronized block it doesn't seem to work properly and both of for loops are run parallelly.How can i run those loops as threadsafe in multi-threaded environment with a synchronized block.Where is the mistake i made my code given?
thanks!
A synchronized block prevents other threads to enter the same or another synchonized block on the same object. You have a single synchronized block here, and only one thread enters it. So all the other threads can execute whatever they want.