Java 8. Thread synchronization issue - java

I have three objects: A, B, and C.
I need such synchronization so that blocks synchronized with objects A and B can be executed in parallel, and when block synchronized with objects A or block synchronized with objects B is executed, block synchronized with objects C cannot be executed. And when block synchronized with objects C is executed, blocks synchronized with objects A and B cannot be executed. I tried to use object C as list, and objects A and B as objects stored in this list, but it did not work. Please tell me, is it possible to somehow configure such synchronization?
import java.util.ArrayList;
import java.util.List;
public class Threads {
public List<Res> lst = new ArrayList();
public void startThreads(){
lst.add(new Res());
lst.add(new Res());
Thread t1 = new Thread(new work1());
Thread t2 = new Thread(new work2());
Thread t3 = new Thread(new work3());
t1.start();
t2.start();
t3.start();
}
public class work1 implements Runnable {
#Override
public void run() {
Method1();
}
}
public class work2 implements Runnable {
#Override
public void run() {
Method2();
}
}
public class work3 implements Runnable {
#Override
public void run() {
Method3();
}
}
public void Method1(){
synchronized (lst.get(0)/*obj A*/){
//some work
}
}
public void Method2(){
synchronized (lst.get(1)/*obj B*/){
//some work
}
}
public void Method3(){
synchronized (lst)/*obj C*/{
//some work
}
}
}
Class Res:
public class Res {
public int number = 0;
}
Class Main:
public class Main {
public static void main(String[] args) throws InterruptedException {
Threads t = new Threads();
t.startThreads();
}
}

In your case simplest (Not recommended) solution is to guard Block A and Block B with different monitor objects and guard Block C with the monitor obects of both A and B.
public void Method1(){
synchronized (A){
//some work
}
}
public void Method2(){
synchronized (B){
//some work
}
}
public void Method3(){
synchronized (A){
synchronized (B){
//some work
}
}
}
Same can be done using Locks as well.
public void Method1(){
lockA.lock();
try{
//some work
} finally {
lockA.unlock();
}
}
public void Method2(){
lockB.lock();
try{
//some work
} finally {
lockB.unlock();
}
}
public void Method3(){
lockA.lock();
try{
lockB.lock();
try{
//some work
} finally {
lockB.unlock();
}
} finally {
lockA.unlock();
}
}
Or you can use read/write lock as suggested by shmosel in the comments.
public void Method1(){
readWriteLock.readLock().lock();
try{
//some work
} finally {
readWriteLock.readLock().unlock();
}
}
public void Method2(){
readWriteLock.readLock().lock();
try{
//some work
} finally {
readWriteLock.readLock().unlock();
}
}
public void Method3(){
readWriteLock.writeLock().lock();
try{
//some work
} finally {
readWriteLock.writeLock().unlock();
}
}
You can also use CountDownLatch for the same purpose, though read/write lock is the easiest one.

Related

java synchronized fails to synchronize

How do I synchronize the run method?
If I use the synchronized keyword here, it doesn't work. It gives me a different output every time?
class MyClass implements Runnable
{
boolean flag;
public MyClass(boolean val)
{
flag=val;
}
public synchronized void run()
{
long id=Thread.currentThread().getId();
int start=(flag)?1:2;
for(int i=start;i<=10;i+=2)
{
System.out.println("Thead "+id+" prints:"+i);
}
}
}
public class Main {
public static void main(String[] args)
{
Thread t1=new Thread(new MyClass(false));
t1.start();
Thread t2=new Thread(new MyClass(true));
t2.start();
}
}
Each thread is using a different instance of MyClass. If you use synchronized on a non static instance, this ensure the method is not executed by several threads at the same for the same MyClass instance. If you want to synchronize for all instances of MyClass, the method has to be static.
class MyClass implements Runnable {
boolean flag;
public MyClass(boolean val)
{
flag=val;
}
private static synchronized void runTask(boolean flag) {
long id=Thread.currentThread().getId();
int start=(flag)?1:2;
for(int i=start;i<=10;i+=2)
{
System.out.println("Thead "+id+" prints:"+i);
}
}
public void run()
{
runTask(flag);
}
}

Wait for another thread to do something

I have two threads, A and B. I want the following:
I want to let A wait until B starts executing f(). Once B starts executing f(), A as well can continue its work.
If B is already executing f() when A informs B for its state, A can continue its work as well.
If however B finished executing f(), A has to wait until B starts executing f() again in the future.
In functions:
// executed by A only
public void waitForB() throws InterruptedException {
// keep waiting until B starts f()
}
// executed within aroundF() only
public void f() {
}
// executed by B only
public void aroundF() {
// 1. mark that we are executing f() and inform A
f()
// 2. unmark
}
I have been trying with Semaphore, Phaser and CyclicBarrier, but I have troubles to understand which to use here.
I managed to implement this with locking manually (see below), but I would like to understand which of the java.util.concurrent classes to use here.
private final Object lock = new Object();
private boolean executing = false;
public void waitForB() throws InterruptedException {
synchronized(lock) {
while(!executing) {
lock.wait();
}
}
}
public void f() {
}
public void aroundF() {
try {
synchronized(lock) {
executing = true;
lock.notify();
}
f();
} finally {
executing = false;
}
}
You can achieve the same semantics (and more) using java.util.concurrent.locks.Lock and an associated java.util.concurrent.locks.Condition, for instance:
public class MyClass {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private boolean executing = false;
public void waitForB() throws InterruptedException {
lock.lock();
try {
while (!executing) {
condition.await();
}
} finally {
lock.unlock();
}
}
public void f() {
}
public void aroundF() {
try {
lock.lock();
try {
executing = true;
condition.signal();
} finally {
lock.unlock();
}
f();
} finally {
executing = false;
}
}
}

java synchronizing access to different critical sections

I have a method which looks like the below.
public class CriticalSections
{
public void mainMethod(boolean b)
{
if (b) {
method1();
}
else {
criticalMethod();
method2();
}
}
private void criticalMethod()
{
System.out.println("in criticalMethod");
}
private void method1()
{
System.out.println("in method1");
}
private void method2()
{
System.out.println("in method2");
}
}
I need to restrict access to these methods such that
When criticalMethod() is accessed by a thread, access to method1() and method2() should be restricted for all other threads.Similarly when method1() and method2() are being accessed by a thread, access to criticalMethod() should be restricted for all other threads.
method1() can individually be accessed concurrently by different threads.
method2() can individually be accessed concurrently by different threads.
method1() and method2() can be accessed concurrently by different threads.
In order to satisfy the 1st access condition I came up with the following code,
but this would not satisfy the other 3 conditions and therefore performance will take a hit.
public class CriticalSections
{
private final Lock lock1 = new ReentrantLock();
private final Lock lock2 = new ReentrantLock();
private final Lock lock3 = new ReentrantLock();
public void mainMethod(boolean b)
{
if (b) {
lock1.tryLock();
try {
method1();
}
finally {
lock1.unlock();
}
}
else {
lock1.tryLock();
try {
lock2.tryLock();
try {
lock3.tryLock();
try {
criticalMethod();
}
finally {
lock3.unlock();
}
}
finally {
lock2.unlock();
}
}
finally {
lock1.unlock();
}
}
lock3.tryLock();
try {
method2();
}
finally {
lock3.unlock();
}
}
private void criticalMethod()
{
System.out.println("in criticalMethod");
}
private void method1()
{
System.out.println("in method1");
}
private void method2()
{
System.out.println("in method2");
}
}
What should be the synchronization mechanism to be used for satisfying the scenarios mentioned?
What you need is an exclusive lock on criticalMethod and shareable locks on methods method1 and method2. The simplest way to achieve this is to use java.util.concurrent.locks.ReentrantReadWriteLock as below:
public class CriticalSections {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public void mainMethod(boolean b) {
if (b) {
method1();
} else {
criticalMethod();
method2();
}
}
private void criticalMethod() {
Lock writeLock = lock.writeLock();
writeLock.lock();
try {
System.out.println("in criticalMethod");
} finally {
writeLock.unlock();
}
}
private void method1() {
Lock readLock = lock.readLock();
readLock.lock();
try {
System.out.println("in method1");
} finally {
readLock.unlock();
}
}
private void method2() {
Lock readLock = lock.readLock();
readLock.lock();
try {
System.out.println("in method2");
} finally {
readLock.unlock();
}
}
}
If you're worried about performance, you can also take a look at java.util.concurrent.locks.StampedLock (Java 8+).

Threads execute not at the same time

I have three threads, each thread have to do some manipulation with the instance(q) of same class (Q), periodically (That's why I use Thread.sleep() in the method somecheck). Main task is to make thread execute not at the same time, so at one time can execute only one thread.
I tried to put content of run method each thread into synchronized (q){}, but I do not understand where to put notify and wait methods.
class Q {
boolean somecheck(int threadSleepTime){
//somecheck__section, if I want to stop thread - return false;
try{
Thread.sleep(threadSleepTime);
} catch (InterruptedException e) {
}
return true;
}
}
class threadFirst extends Thread {
private Q q;
threadFirst(Q q){this.q=q;}
public void run(){
do{
//Working with object of class Q
}
while(q.somecheck(10));
}
}
class threadSecond extends Thread {
private Q q;
threadSecond(Q q){this.q=q;}
public void run(){
do{
//Working with object of class Q
}
while(q.somecheck(15));
}
}
class threadThird extends Thread {
private Q q;
threadThird(Q q){this.q=q;}
public void run(){
do{
//Working with object of class Q
}
while(q.somecheck(20));
}
}
class run{
public static void main(String[] args) {
Q q = new Q();
threadFirst t1 = new threadFirst(q);
threadSecond t2 = new threadSecond(q);
threadThird t3 = new threadThird(q);
t1.start();
t2.start();
t3.start();
}
}
You don't need to put any notify() and wait() methods if you use synchronized blocks inside all of the methods, for example:
class threadFirst extends Thread {
...
public void run() {
synchronized (q) {
//your loop here
}
}
...
}

Printing "Hello" and "world" multiple times using two threads in java

Assume that one thread prints "Hello" and another prints "World". I have done it successfully for one time, as follows:
package threading;
public class InterThread {
public static void main(String[] args) {
MyThread mt=new MyThread();
mt.start();
synchronized(mt){
System.out.println("Hello");
try {
mt.wait();
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread extends Thread{
public void run(){
synchronized(this){
System.out.println("World!");
notify();
}
}
}
How do I do it for multiple time printing, say for 5 times? I tried putting for loop around the synchronized block, but of no use.
Here being two interdependent threads, we need two synchronizing objects. they could be one of many things. one integer, another object; one Boolean another object; both object; both semaphores and so on. the synchronization technique could be either Monitor or Semaphore any way you like, but they have to be two.
I have modified your code to use semaphore instead of Monitor. The Semaphore works more transparently. You can see the acquire and release happening. Monitors are even higher constructs. Hence Synchronized works under the hood.
If you are comfortable with the following code, then you can convert it to use Monitors instead.
import java.util.concurrent.Semaphore;
public class MainClass {
static Semaphore hello = new Semaphore(1);
static Semaphore world = new Semaphore(0);
public static void main(String[] args) throws InterruptedException {
MyThread mt=new MyThread();
mt.hello = hello;
mt.world = world;
mt.start();
for (int i=0; i<5; i++) {
hello.acquire(); //wait for it
System.out.println("Hello");
world.release(); //go say world
}
}
}
class MyThread extends Thread{
Semaphore hello, world;
public void run(){
try {
for(int i = 0; i<5; i++) {
world.acquire(); // wait-for it
System.out.println(" World!");
hello.release(); // go say hello
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadSeq {
Object hello = new Object();
Object world = new Object();
public static void main(String[] args) throws InterruptedException {
for(int i=0; i<6;i++){
Runnable helloTask = new Runnable(){
#Override
public void run(){
new ThreadSeq().printHello();
}
};
Runnable worldTask = new Runnable(){
#Override
public void run(){
new ThreadSeq().printWorld();
}
};
Thread t1 = new Thread(helloTask);
Thread t2 = new Thread(worldTask);
t1.start();
t1.join();
t2.start();
t2.join();
}
}
public void printHello(){
synchronized (hello) {
System.out.println("Hello");
}
}
public void printWorld(){
synchronized (world) {
System.out.println("World");
}
}
}
The goal here is to synchronize threads so that when one is done it notify the other. If I have to make it, it would be 2 threads executing the same code with different data. Each thread has its own data ("Hello" and true to T1, "World" and false to t2), and share a variable turn plus a separate lock object.
while(/* I need to play*/){
synchronized(lock){
if(turn == myturn){
System.out.println(mymessage);
turn = !turn; //switch turns
lock.signal();
}
else{
lock.wait();
}
}
}
Before you start trying to get it to work five times you need to make sure it works once!
Your code is not guaranteed to always print Hello World! - the main thread could be interrupted before taking the lock of mt (note that locking on thread objects is generally not a good idea).
MyThread mt=new MyThread();
mt.start();
\\ interrupted here
synchronized(mt){
...
One approach, that will generalise to doing this many times, is to use an atomic boolean
import java.util.concurrent.atomic.AtomicBoolean;
public class InterThread {
public static void main(String[] args) {
int sayThisManyTimes = 5;
AtomicBoolean saidHello = new AtomicBoolean(false);
MyThread mt=new MyThread(sayThisManyTimes,saidHello);
mt.start();
for(int i=0;i<sayThisManyTimes;i++){
while(saidHello.get()){} // spin doing nothing!
System.out.println("Hello ");
saidHello.set(true);
}
}
}
class MyThread extends Thread{
private final int sayThisManyTimes;
private final AtomicBoolean saidHello;
public MyThread(int say, AtomicBoolean said){
super("MyThread");
sayThisManyTimes = say;
saidHello = said;
}
public void run(){
for(int i=0;i<sayThisManyTimes;i++){
while(!saidHello.get()){} // spin doing nothing!
System.out.println("World!");
saidHello.set(false);
}
}
}
This is in C:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t hello_lock, world_lock;
void printhello()
{
while(1) {
pthread_mutex_lock(&hello_lock);
printf("Hello ");
pthread_mutex_unlock(&world_lock);
}
}
void printworld()
{
while(1) {
pthread_mutex_lock(&world_lock);
printf("World ");
pthread_mutex_unlock(&hello_lock);
}
}
int main()
{
pthread_t helloThread, worldThread;
pthread_create(&helloThread,NULL,(void *)printhello,NULL);
pthread_create(&helloThread,NULL,(void *)printhello,NULL);
pthread_join(helloThread);
pthread_join(worldThread);
return 0;
}
There are two thread and both has its own data ("Hello" and true to ht, "World" and false to wt), and share a variable objturn.
public class HelloWorldBy2Thread {
public static void main(String[] args) {
PrintHelloWorld hw = new PrintHelloWorld();
HelloThread ht = new HelloThread(hw);
WorldThread wt = new WorldThread(hw);
ht.start();
wt.start();
}
}
public class HelloThread extends Thread {
private PrintHelloWorld phw;
private String hello;
public HelloThread(PrintHelloWorld hw) {
phw = hw;
hello = "Hello";
}
#Override
public void run(){
for(int i=0;i<10;i++)
phw.print(hello,true);
}
}
public class WorldThread extends Thread {
private PrintHelloWorld phw;
private String world;
public WorldThread(PrintHelloWorld hw) {
phw = hw;
world = "World";
}
#Override
public void run(){
for(int i=0;i<10;i++)
phw.print(world,false);
}
}
public class PrintHelloWorld {
private boolean objturn=true;
public synchronized void print(String str, boolean thturn){
while(objturn != thturn){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str+" ");
objturn = ! thturn;
notify();
}
}
In simple way we can do this using wait() and notify() without creating any extra object.
public class MainHelloWorldThread {
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
Thread t1 = new Thread(() -> {
try {
helloWorld.printHello();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
helloWorld.printWorld();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// printHello() will be called first
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}
class HelloWorld {
public void printHello() throws InterruptedException {
synchronized (this) {
// Infinite loop
while (true) {
// Sleep for 500ms
Thread.sleep(500);
System.out.print("Hello ");
wait();
// This thread will wait to call notify() from printWorld()
notify();
// This notify() will release lock on printWorld() thread
}
}
}
public void printWorld() throws InterruptedException {
synchronized (this) {
// Infinite loop
while (true) {
// Sleep for 100ms
Thread.sleep(100);
System.out.println("World");
notify();
// This notify() will release lock on printHello() thread
wait();
// This thread will wait to call notify() from printHello()
}
}
}
}

Categories