Synchronized in Java

Synchronized In Java

Java - Intrinsic Locks and Synchronization

Last Updated: 15-10-2019

Multi-threaded programs may often come to a situation(情况) where multiple threads try to access the same resources and finally produce erroneous and unforeseen results.

So it needs to be made sure by some synchronization method that only one thread can access the resource at a given point of time.

在使用多线程程序时 可能经常会遇到多个线程尝试访问相同资源并最终产生错误和无法预料的结果的情况。

因此,多线程程序需要通过某种同步方法来确保在给定的时间点只有一个线程可以访问资源。

Java provides a way of creating threads and synchronizing their task by using synchronized blocks.

Java提供了一种使用同步块创建线程并同步其任务的方法。

Synchronized blocks in Java are marked with the synchronized keyword. A synchronized block in Java is synchronized on some object. All synchronized blocks synchronized on the same object can only have one thread executing inside them at a time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.

Java中的已同步块都用sync关键字标记。 Java中的同步块在某些对象上同步。 在同一对象上同步的所有同步块一次只能在其中一个线程内执行。 尝试进入同步块的所有其他线程将被阻塞,直到同步块内的线程退出该块为止。

Following is the general form of a synchronized block: 以下是同步块的一般形式

1
2
3
4
5
6
7
8
9
10
// Only one thread can execute at a time. 
// sync_object is a reference to an object
// whose lock associates with the monitor.
// The code is said to be synchronized on
// the monitor object
synchronized(sync_object)
{
// Access shared variables and other
// shared resources
}

This synchronization is implemented in Java with a concept called monitors. Only one thread can own a monitor at a given time. When a thread acquires a lock, it is said to have entered the monitor. All other threads attempting to enter the locked monitor will be suspended until the first thread exits the monitor.

此同步是在Java中通过一个称为监视器的概念实现的。 在给定的时间,只有一个线程可以拥有一个监视器。 当线程获取锁时,据说它已进入监视器。 试图进入锁定监视器的所有其他线程将被挂起,直到第一个线程退出监视器。

Following is an example of multi threading with synchronized.

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
package Keyword.Synchronized;
/**
* @author yichangkong
* @create 2020-08-10-15:57
*/
// A Java program to demonstrate working of synchronized.
// A Class used to send a message
class Sender {
public void send(String msg) {
System.out.println("Sending\t" + msg);
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
System.out.println("\n" + msg + "Sent");
}
}

// Class for send a message using Threads
class ThreadedSend extends Thread {
private String msg;
Sender sender;

// Recieves a message object and a string
// message to be sent
ThreadedSend(String m, Sender obj) {
msg = m;
sender = obj;
}

public void run() {
// Only one thread can send a message
// at a time.
synchronized (sender) {
// synchronizing the snd object
sender.send(msg);
}
}
}

// Driver class
public class MySynchronized {
public static void main(String args[]) {
Sender snd = new Sender();
ThreadedSend S1 = new ThreadedSend(" Hi ", snd);
ThreadedSend S2 = new ThreadedSend(" Bye ", snd);

// Start two threads of ThreadedSend type
S1.start();
S2.start();

// wait for threads to end
try {
S1.join();
S2.join();
} catch (Exception e) {
System.out.println("Interrupted");
}
}
}

Output:

Code

1
2
3
4
5
6
Sending     Hi 

Hi Sent
Sending Bye

Bye Sent

The output is same every-time we run the program.每次我们运行程序时,输出都是相同的。意思就是同步代码块起到作用了

In the above example, we chose to synchronize the Sender object inside the run() method of the ThreadedSend class. Alternately, we could define the whole send() block as synchronized and it would produce the same result.

在上面的示例中,我们选择在ThreadedSend类的run()方法内同步Sender对象。 或者,我们也可以将整个send()块定义为已同步,并且将产生相同的结果。

Then we don’t have to synchronize the Message object inside the run() method in ThreadedSend class.

然后,我们不必在ThreadedSend类的run()方法内同步Message对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// An alternate implementation to demonstrate 
// that we can use synchronized with method also.
class Sender
{
public synchronized void send(String msg)
{
System.out.println("Sending\t" + msg );
try
{
Thread.sleep(1000); //以便于测试synchronized的有效性,就故意将线程sleep 让其他线程进行run
}
catch (Exception e)
{
System.out.println("Thread interrupted.");
}
System.out.println("\n" + msg + "Sent");
}
}

We do not always have to synchronize a whole method. Sometimes it is preferable to synchronize only part of a method. Java synchronized blocks inside methods makes this possible.

我们并不总是必须同步整个方法。 有时最好只同步一部分方法。 同步方法内部的一些方法块更加行之有效 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// One more alternate implementation to demonstrate 
// that synchronized can be used with only a part of
// method
class Sender
{
public void send(String msg)
{
synchronized(this)
{
System.out.println("Sending\t" + msg );
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println("Thread interrupted.");
}
System.out.println("\n" + msg + "Sent");
}
}
}

This article is contributed by Souradeep Barua. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above

Attention reader! Don’t stop learning now.

本文由Souradeep Barua提供。 如果发现任何不正确的地方,或者想分享有关上述主题的更多信息,请发表评论。

读者注意! 请不要停止学习