Previous article - SYNCHRONIZATION AND OBJECT LOCK, PART 1
To make any method synchronized we need to use “synchronized” keyword. It prevents any method for a shared resource. When a method gets called, the calling thread acquires the object lock. The acquired lock won’t be released until the thread completes its execution.
Syntax:
1
2
3
access_specifier synchronized return_type method_name(parameters) {
//Set of statements
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class WorkerClass {
synchronized void printPot(int n) { //method synchronized
System.out.println(Thread.currentThread()
.getName() + ": " + n);
try {
Thread.sleep(500);
} catch (Exception e) {
System.out.println(e);
}
}
}
class Thread1 extends Thread {
WorkerClass p;
Thread1(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(5);
}
}
class Thread2 extends Thread {
WorkerClass p;
Thread2(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(8);
}
}
public class Solution {
public static void main(String args[]) {
WorkerClass wc = new WorkerClass();
Thread1 t1 = new Thread1(wc);
Thread2 t2 = new Thread2(wc);
t1.start();
t2.start();
}
}
Output:
In the above example we have used synchronized keyword. Only one thread will execute the method “printPot” and other t2 will only be allowed once t1 will release the acquired object lock.
There may be a case when we don’t want to synchronize the method but want some statements to be synchronized. In such a case we can keep those lines inside a synchronized block. It works the same as the synchronized method. Object lock is accessed in case of synchronized block.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class WorkerClass {
void printPot(int n) {
synchronized(this) { //synchronized block
System.out.println(Thread.currentThread()
.getName() + ": " + n);
}
}
}
class Thread1 extends Thread {
WorkerClass p;
Thread1(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(10);
}
}
class Thread2 extends Thread {
WorkerClass p;
Thread2(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(20);
}
}
public class Solution {
public static void main(String args[]) {
WorkerClass wc = new WorkerClass();
Thread1 t1 = new Thread1(wc);
Thread2 t2 = new Thread2(wc);
t1.start();
t2.start();
}
}
Every object has a lock that gets created when the object is created.
In Java threads, we need to acquire the object lock to enter synchronized block or method. All other threads have to wait until the current entered monitor releases the object lock. There may be a condition of more than one object. In that case, multiple objects will acquire the object lock and enter into the synchronized block or method. To avoid this static synchronization is used. A “synchronized” keyword will be used with static block to implement static synchronization.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
Java Implementation:
class WorkerClass {
synchronized static void printPot(int n) { //static synchronized method
System.out.println(Thread.currentThread()
.getName() + ":" + n);
}
}
class Thread1 extends Thread {
WorkerClass p;
Thread1(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(10);
}
}
class Thread2 extends Thread {
WorkerClass p;
Thread2(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(20);
}
}
class Thread3 extends Thread {
WorkerClass p;
Thread3(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(30);
}
}
class Thread4 extends Thread {
WorkerClass p;
Thread4(WorkerClass p) {
this.p = p;
}
public void run() {
p.printPot(40);
}
}
public class Solution {
public static void main(String args[]) {
WorkerClass obj1 = new WorkerClass(); //first object
WorkerClass obj2 = new WorkerClass(); //second object
Thread1 t1 = new Thread1(obj1);
Thread2 t2 = new Thread2(obj1);
Thread3 t3 = new Thread3(obj2);
Thread4 t4 = new Thread4(obj2);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Code Snippet 1
Code Snippet 2
Code Snippet 3