65.9K
CodeProject 正在变化。 阅读更多。
Home

Java 中的线程:深入研究 synchronized

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2021 年 6 月 19 日

CPOL

2分钟阅读

viewsIcon

5184

深入理解 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]

上述程序可以成功编译并运行,产生预期的同步输出。这无需解释。线程 t1t2 使用类级别锁“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]

上述程序可以成功编译并运行,产生预期的同步输出。这无需解释。线程 t1t2 使用对象级别锁“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 日:初始修订
© . All rights reserved.