Given this code:
public class Messager implements Runnable {
public static void main(String[] args) {
new Thread(new Messager("Wallace")).start();
new Thread(new Messager("Gromit")).start();
}
private String name;
public Messager(String name) { this.name = name; }
public void run() {
message(1); message(2);
}
private synchronized void message(int n) {
System.out.print(name + "-" + n + " ");
}
}
I understand that the synchronized keyword makes the thread dependent on the object's lock. Questions:
a) Is the lock released as soon as the method marked as synchronized finishes? Or as soon as the thread's run() method finishes
b) Can I ensure that any one of the threads will print its name and 1 2 before the other?
A. Yes. It's released as soon as the synchronized function finishes.
B. Yes. You can, but if you wanted to do so, why would you write multithreaded code in the first place? synchronized guarantees atomicity, not anything regarding the order, but you can enforce order by waiting for a flag to change. Anyway, what you are trying to enforce is sequentiality. You get this for free in single-threaded environments :)
Related
Recently I've started looking into multithreading, and I have a question, perhaps more experienced ones could help.
My program creates two parallel threads, each of them prints counts from 0 to 19 (the NumbersPrinter class, which implements the Runnable interface).
class NumbersPrinter implements Runnable {
private Mediator mediator;
private String name;
private int makeActionOnCount;
public NumbersPrinter(Mediator mediator, String name, int makeActionOnCount) {
this.mediator = mediator;
this.name = name;
this.makeActionOnCount = makeActionOnCount;
}
#Override
public void run() {
for(int i = 0; i<20; i++){
try {
synchronized(this.mediator) {
if(this.mediator.actionInProgress.get()) {
System.out.println(name + " waits");
wait();
}
}
System.out.println(this.name + " says " + i);
Thread.sleep(500);
if(i == makeActionOnCount) {
synchronized(this.mediator) {
System.out.println(this.name + " asks Mediator to perform action...");
this.mediator.performAction();
this.mediator.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
When one of the threads reaches a certain number (defined in the makeActionOnCount variable), it starts performing a certain action that stops the execution of the second counter. The action lasts 5 seconds and after that both counters continue to count.
The counters are interconnected through an instance of the Mediator class, the performAcyion() method also belongs to the instance of the Mediator class.
import java.util.concurrent.atomic.AtomicBoolean;
class Mediator {
public AtomicBoolean actionInProgress = new AtomicBoolean(false);
public Mediator() {
}
public void performAction() throws InterruptedException {
actionInProgress.set(true);
System.out.println("Action is being performed");
Thread.sleep(5000);
System.out.println("Action has been performed");
actionInProgress.set(false);
}
}
Here's the Main class:
class Main {
public static void main(String[] args) throws InterruptedException{
Mediator mediator = new Mediator();
NumbersPrinter data = new NumbersPrinter(mediator, "Data", 10);
NumbersPrinter lore = new NumbersPrinter(mediator, "Lore", 5);
Thread oneThread = new Thread(data);
Thread twoThread = new Thread(lore);
System.out.println("Program started");
oneThread.start();
twoThread.start();
oneThread.join();
twoThread.join();
System.out.println("Program ended");
}
The way the program is written now - works fine, but I don't quite understand what exactly should I write in the first synchronized block, because if you delete all content from it, the program still works, since the counter that does not execute the performAction() method stops 'cause the counter cannot access the monitor of the Mediator object 'cause it is busy with the parallel counter. AtomicBoolean variable and checking it also makes no sense.
In other words, I may not use the wait () and notify () constructs at all, as well as the value of the AtomicBoolean variable, and just check access to the Mediator object's monitor every new iteration using an empty synchronized block. But I've heard that an empty synchronized block is a bad practice.
I am asking for help on how to rewrite the program to use the synchronized block and the wait() and notify() methods correctly.
Maybe I'm syncing on the wrong object? How would you solve a similar problem?
Thanks in advance
public class Test implements Runnable{
private String name;
public Test(String name){
this.name = name;
}
public void run() {
blah(name);
}
public synchronized void blah(String obj) {
System.out.println("Here: "+obj);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Test x = new Test("X");
Test y = new Test("Y");
Thread tx = new Thread(x);
Thread ty = new Thread(y);
tx.start();
ty.start();
}
This example should help me to understand synchronization, but I don't. This is because if I remove the word synchronize, it printed the same output (random)
Synchronization is irrelevant here because your two threads are each synchronizing on their own Runnable. There is no shared lock, and no shared data.
If you pass the same Runnable instance into each Thread then they will share the same lock. If your Runnable does something in a thread-unsafe way (like using ++ to increment a shared variable (an instance variable of the Runnable), or adding the entry to a shared ArrayList) then you can create a situation where removing synchronization can make the code break (with the understanding that breakage may not happen reliably, that's what makes multithreaded programming fun).
Making toy examples like this is not a good preparation for real-life multithreading. Threads shouldn't be in the business of implementing locking, they should be accessing data objects that enforce their own invariants.
Your example is technically correct, but there is no timing dependent conflict in your synchronized block. As such, there is no chance that you will see different output, regardless of the ordering of the calls.
In addition, you create two resources, and there is no cross-thread communication between the two resources, so effectively you've tested two synchronized blocks once each.
You need an example that can break when not synchronized.
Here is an example that can break
public class Counter {
int count;
public Counter() {
count = 0;
}
public int getCount() {
return count;
}
public /* need synchronized here */ void update(int value) {
int buffer = 0;
buffer = buffer + count;
buffer = buffer + value;
count = buffer;
}
}
public class UpdateCounter extends Thread {
public UpdateCounter(Counter counter, int amount) {
this.counter = counter;
this.name = name;
}
public void run() {
System.out.printf("Adding %d to count\n", amount);
counter.update(amount);
System.out.printf("Count is %d\n", counter.getCount());
}
}
public static void main(String[] args) {
Counter counter = new Counter();
UpdateCounter x = new UpdateCounter(counter, 30);
UpdateCounter y = new UpdateCounter(counter, 100);
x.start();
y.start();
}
With an example like this, one would eventually see a series of lines that indicated some value was being added to the counter, but the counter would update by the wrong value.
This is because one thread will eventually get paused with a buffer holding the "next" value, and the other thread will race across the same block of code, storing its "next" value into count. Then the paused thread will un-pause, and store its "next" value effectively removing the amount added by the thread that raced ahead of it.
By adding the synchronized keyword, only one thread is allowed entry into the update block, and the race condition I described above cannot occur.
Note that this is an example that can fail with bad synchronization, and not a good way to implement a counter.
I have created the next simple class code (which is just for my question clarification):
public class StudioClass {
synchronized void dancing(String name) {
System.out.println(name + " is dancing");
}
synchronized void singing(String name) {
System.out.println(name + " is singing");
}
public class StudentA extends Thread {
String name;
public StudentA(String name) {
this.name = name;
}
#Override
public void run() {
dancing(name);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
singing(name);
}
}
public class StudentB extends Thread {
String name;
public StudentB(String name) {
this.name = name;
}
#Override
public void run() {
singing(name);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
dancing(name);
}
}
In this example the order actions of student A are: dancing and then singing and student B are: singing and than dancing. This scenario is a classic situation for a Deadlock.
How can I deliberately create a Deadlock situation by these actions?
The simple solution (as I understand) is to define each action (singing & dancing) as different objects, but I wonder is there any other way keeping them as methods?
I don't see any potential deadlocks with your code.
A thread executes a single synchronized method and during this execution I don't see conditions which will make two threads to wait for each other in a indefinite way.
At worst, a thread waits for that the other thread releases the lock on the method.
You should imagine a more complex scenario with share object between threads or inter-dependencies between actions.
You're not using any shared resource. Without that there's no question of a deadlock.
If there was a situation like A, B both require a lock on shared variables s,t to perform a dance and song and the locks were acquired in the following way (among others):
A_lock(s)
A_lock(t)
dance
sing
A_release(t)
A_release(s)
B_lock(t)
B_lock(s)
dance
sing
B_release(s)
B_release(t)
There is a chance of deadlock if A acquires s and B acquires t and wait for each other to release locks for eternity.
I do realize that this topic has been discussed at many places. But all of them talk about it's usage in multi-threaded environment.
In this following example, why is notify() supposed to be surrounded by synchronized? It goes in vain when the keyword is used, which it is supposed to do. But why the exception, java.lang.IllegalMonitorStateException, when it is not used?
public class HelloWorld {
public static void main(String[] args) {
ABC c = new ABC();
c.put(0);
}
}
class ABC {
public synchronized void put(int value) { // why synchronized now!
System.out.println("Put: " + value);
notify();
}
}
You supposed to use synchronized is because the lock is re-entrant, meaning that it can be acquired multiple times by the same thread.
In other words if your thread already holds the lock on an object it doesn't have to wait on itself.
When I try to execute the piece of code, I am getting output like 12221121212121221212. When I declare the method as synchronized, it should not allow the other thread to take over the control
package com.test;
public class TestProject extends Thread {
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.print(getName());
}
}
}
public static void main(String[] args) throws InterruptedException {
TestProject myProject = new TestProject();
TestProject myProject1 = new TestProject();
myProject.setName("1");
myProject1.setName("2");
myProject.start();
myProacject1.start();
}
}
So, how do I alter the code to get a output of 11111111112222222222 or 22222222221111111111 in sequential format?
You are synchronizing on this, i.e. on the TestProject object. Since you have two separate objects, you have two separate locks. Consequently, both threads can enter the synchronized section irrespective of what the other thread is doing.
To synchronize across instances of TestProject you need a static lock:
public class TestProject extends Thread {
private static final Object lock = new Object();
public void run() {
synchronized (lock) {
...
Java uses biased locking by default. This means a lock will favour the last thread to access a lock. If you consider that one thread can start, run and finish before the other even starts I would expect you get one thread running to completion before the other starts most of the time.
I have just noticed you lock outside the loop. This will guarantee you also run one thread to completion before the other starts.
This is how you can enforce fair alternation of threads.
public class TestProject implements Runnable {
private final Lock lock;
public TestProject(Lock lock) {
this.lock = lock;
}
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
System.out.print(Thread.currentThread().getName());
} finally {
lock.unlock();
}
}
}
public static void main(String... ignored) {
Lock lock = new ReentrantLock(true);
new Thread(new TestProject(lock), "1").start();
new Thread(new TestProject(lock), "2").start();
}
}
can print
12121212121212121212
Note: if you make the lock non-fair you can get (change the true to false)
11111111112222222222
Note: if you want fair alternation between two tasks, it much simpler to use one thread and a loop.
public static void main(String... ignored) {
for (int i = 0; i < 10; i++) {
// task 1
System.out.print("1");
// task 2
System.out.print("2");
}
}
you can also use join method on myProject1 so that it waits for the other thread to finish
these are the following method that can be used to achieve synchronization among the thread
1). use a static global lock and pass that object variable as argument to the synchronized block
2). use join()
3). create a instance for the Object class and pass that as an argument to the synchronized block like this Object myObject = TestProject.class now pass myObject to the synchronized block
using either of the above ways we can achieve synchronization