Java 中的线程:深入研究 synchronized





5.00/5 (1投票)
深入理解 synchronized 关键字的含义
引言
一些智者说过:“不要以貌取人,很多东西隐藏在潜意识中”。这种说法对于 synchronized 函数是否成立呢?让我们来看看。请看以下程序
locks.java
-----------
class processor implements Runnable{
public void run() {
display();
}
public void display() {
synchronized (processor.lock){
for (int i = 0 ; i<= 5; i++) {
System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
}
}
}
}
class locks {
public static void main(String[] args) {
processor p1 = new processor();
processor p2 = new processor();
Thread t1 = new Thread(p1, "t1");
Thread t2 = new Thread(p2, "t2");
t1.start();
t2.start();
}
}
Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]
上述程序可以成功编译并运行,产生预期的同步输出。这无需解释。线程 t1
和 t2
使用类级别锁“processor.lock
”进行同步,确保 display()
函数中的 for
循环由 processor 类的任何对象创建的唯一一个线程执行。
现在,请看一个与上述程序类似,但略有不同的程序。
locks.java
----------
class processor implements Runnable{
public void run() {
display();
}
// Observe the synchronized statement below
public static synchronized void display() {
for (int i = 0 ; i<= 5; i++) {
System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
}
}
}
class locks {
public static void main(String[] args) {
processor p1 = new processor();
processor p2 = new processor();
Thread t1 = new Thread(p1, "t1");
Thread t2 = new Thread(p2, "t2");
t1.start();
t2.start();
}
}
Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]
上述程序可以成功编译并运行,产生与先前程序完全相同的预期输出。 唯一的改变是我们将 display 声明为静态同步函数()。 我们得到了与先前程序完全相同的输出。
public static synchronized void display() {
....
....
....
}
EXACTLY EQUALS
public void display() {
synchronized(process.lock) {
....
....
....
....
}
}
And NOT EQUAL TO
public void display() {
......
......
......
synchronized(process.lock){
....
....
....
}
}
因此,当你看到一个函数声明为 static
synchronized 时,这意味着其中的代码受到类级别锁的保护。
现在让我们来看 对象
锁。请看以下程序
locks.java
-----------
class processor implements Runnable{
public void run() {
display();
}
public void display() {
synchronized (this){
for (int i = 0 ; i<= 5; i++) {
System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
}
}
}
}
class locks {
public static void main(String[] args) {
processor p1 = new processor();
processor p2 = new processor();
Thread t1 = new Thread(p1, "t1");
Thread t2 = new Thread(p1, "t2");
t1.start();
t2.start();
}
}
Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]
上述程序可以成功编译并运行,产生预期的同步输出。这无需解释。线程 t1
和 t2
使用对象级别锁“this
”进行同步,确保 display()
函数中的 for
循环由 processor 类的唯一一个对象创建的唯一一个线程执行。
现在,请看一个与上述程序类似,但略有不同的程序。
locks.java
----------
class processor implements Runnable{
public void run() {
display();
}
// Observe the synchronized statement below
public synchronized void display() {
for (int i = 0 ; i<= 5; i++) {
System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
}
}
}
class locks {
public static void main(String[] args) {
processor p1 = new processor();
processor p2 = new processor();
Thread t1 = new Thread(p1, "t1");
Thread t2 = new Thread(p1, "t2");
t1.start();
t2.start();
}
}
Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]
上述程序可以成功编译并运行,产生与先前程序完全相同的预期输出。 唯一的改变是我们将 display 声明为 synchronized 函数()。 我们得到了与先前程序完全相同的输出。
public synchronized void display() {
....
....
....
}
EXACTLY EQUALS
public void display() {
synchronized(this) {
....
....
....
....
}
}
And NOT EQUAL TO
public void display() {
......
......
......
synchronized(this){
....
....
....
}
}
因此,当你看到一个函数声明为 synchronized 时,这意味着其中的代码受到对象级别锁的保护。
本练习的目的是理解 synchronized 函数内部使用对象级别锁,而静态 synchronized 函数内部使用类级别锁来保护其所有代码。 确实,很多东西隐藏在 Java 中 synchronized 关键字的潜意识中。 你怎么说?
关注点
将 static synchronized 应用于方法时,指的是类级别锁,而将 mere synchronized 应用于方法时,指的是对象级别锁。
读者们,请随时留下评论,告诉我这篇文章对您是否有帮助。 这让我了解是否需要添加更多内容作为解释的一部分。 您的反馈非常受欢迎。 谢谢!
历史
- 2021 年 6 月 19 日:初始修订