[英]thread: Synchronized Block
我對同步塊有疑問。 執行以下代碼后,輸出為:
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2
我期望輸出,因為只有一個線程會首先執行同步塊,然后只有第二個線程才能訪問synchornized塊。 可能是我了解錯誤的概念?
package com.blt;
public class ThreadExample implements Runnable {
public static void main(String args[])
{
System.out.println("A");
Thread T=new Thread(new ThreadExample());
Thread T1=new Thread(new ThreadExample());
System.out.println("B");
T.setName("thread 1");
T1.setName("thread 2");
System.out.println("C");
T.start();
System.out.println("D");
T1.start();
}
synchronized public void run()
{
for(int i=0; i<5; i++)
{
try
{
System.out.println("Inside run=>"+Thread.currentThread().getName());
Thread.currentThread().sleep(2000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
您的每個線程都在不同的對象上同步。 所以是的,他們不會互相鎖定。 但更重要的是, run
方法是為Runnable
接口定義的, 沒有同步修飾符,因此您不應在其中添加一個(如您已經看到的那樣,它沒有您預期的效果)。
要記住的關鍵是,當您在方法上使用synced修飾符時:
public synchronized void someMethod();
實際上,它與使用synchronized(this)
。 在這兩種情況下,您都鎖定在對象監視器上。 如果有多個對象,則有多個監視器。
這是您自己的示例的修改版本,它將按您的預期工作。 它使用一個通用的對象監視器(在本例中為您的類本身),以便同步按預期進行:
public class ThreadExample implements Runnable {
public static void main(String args[]) {
System.out.println("A");
Thread T = new Thread(new ThreadExample());
Thread T1 = new Thread(new ThreadExample());
System.out.println("B");
T.setName("thread 1");
T1.setName("thread 2");
System.out.println("C");
T.start();
System.out.println("D");
T1.start();
}
public void run() {
synchronized (ThreadExample.class) {
for (int i = 0; i < 5; i++) {
try {
System.out.println("Inside run=>"
+ Thread.currentThread().getName());
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
您的問題是,如果兩個同步塊未鎖定在同一監視器上,則它們不是互斥的。
請記住,同步方法鎖定在this
監視器上-您的代碼等效於:
public void run() {
synchronized(this) {
//your code here
}
}
由於您創建了ThreadExample
兩個實例,因此每個實例都有一個不同的this
。
您可以通過在兩個線程中使用相同的鎖來解決問題,例如:
public void run() {
synchronized(ThreadExample.class) {
//your code here
}
}
甚至更好,只創建一個實例ThreadExample
如指出Quoi 。
您已經創建了ThreadExample
兩個Object,因此每個線程都有不同的synchronized
方法。
創建單個對象並將引用傳遞給線程,您將看到同步的效果。
ThreadExample thex = new ThreadExample();
Thread T=new Thread(thex);
Thread T1=new Thread(thex);
這里兩個線程將使用相同的synchronized
方法。
嗯,您正在同步每個線程的run方法。 Thread1不會嘗試運行Thread2的run方法,反之亦然。 這就是為什么它實際上與根本不同步的原因相同。
您正在創建該類的兩個實例,並且正在類上進行同步,因此它們將獨立運行,因為沒有通用鎖。 他們將繼續獨立運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.