[英]Multi threading
我對多線程有一個想法,但我從未嘗試過。 因此,當我看到我的應用程序在工作時...我沒有看到任何擴展Thread的類來創建Thread
。 因此,當2個對象嘗試同時訪問變量時, synchronized
使用synchronized
關鍵字。我們使用synced來避免沖突。
例:
public class Test {
private static int count = 0;
public static synchronized void incrementCount() {
count++;
}
}
如果測試類使用由對象然后是有意義的加synchronized
到incrementcount()
但是,當你不延長Thread
或Runnable
那么有什么用書面synchronized
。
同步不適用於線程或Runnable,它用於由多個線程訪問的數據結構,以確保每個線程以不破壞其數據的方式訪問它們。 您自己的示例是一個簡單的例子,其中count以一種不是線程安全的方式遞增( 使用++,請參見此問題 ),因此需要鎖定以確保一次僅一個線程可以遞增它。
如果還有其他訪問count的代碼,則還需要同步它,以便可見count的更新。 如果您要做的只是增加一個計數器,那么使用java.util.concurrent.atomic.AtomicInteger
類的類更有意義,並且您可以完全不使用synced關鍵字。
為了使同步有意義,它確實假定存在多個線程。 即使您自己的代碼沒有創建新的線程,在某些情況下也可能有多個線程在調用您的代碼(例如在servlet容器中,該容器管理線程池並為每個傳入請求分配線程)。
一個類不需要extend Thread
或implements Runnable
來將其方法標記為已同步,以防止多線程訪問
您的類可能是某個其他線程類的參數,並且該線程類可能具有多個實例。 為了提供強大的數據一致性,您已經保護了代碼和數據的關鍵部分。
只需更改您的代碼示例,如下所示。
我在對象級別而非類級別演示“已synchronized
”( static synchronized
)
class Test {
private int count = 0;
public void incrementCount() {
count++;
System.out.println("Count:"+count);
}
}
class MyRunnable implements Runnable{
private Test test = null;
public MyRunnable(Test t){
this.test = t;
}
public void run(){
test.incrementCount();
}
}
public class SynchronizedDemo{
public static void main(String args[]){
Test t = new Test();
for ( int i=0; i<10; i++){
new Thread(new MyRunnable(t)).start();
}
}
}
您的類Test
已作為參數傳遞給線程MyRunnable
。 現在,您已經創建了多個線程實例。 在沒有synchronized
關鍵字的情況下,輸出是不可預測的,如下所示。
java SynchronizedDemo
Count:2
Count:3
Count:2
Count:7
Count:6
Count:5
Count:4
Count:10
Count:9
Count:8
如果我改變
public void incrementCount() {
至
public synchronized void incrementCount() {
輸出為:
Count:1
Count:2
Count:3
Count:4
Count:5
Count:6
Count:7
Count:8
Count:9
Count:10
另一方面,您已將您的方法設置為static synchronized
。 That means lock is maintained at class level instead of object level.
請查看oracle文檔頁面以更好地理解。
缺少“ static synchronized
”的代碼演示
class Test {
private static int count = 0;
public static void incrementCount() {
count++;
System.out.println("Count:"+count);
}
}
class MyRunnable implements Runnable{
private Test test = null;
public MyRunnable(Test t){
this.test = t;
}
public void run(){
test.incrementCount();
}
}
public class SynchronizedDemo{
public static void main(String args[]){
for ( int i=0; i<10; i++){
Test t = new Test();
new Thread(new MyRunnable(t)).start();
}
}
}
輸出:
Count:5
Count:4
Count:3
Count:2
Count:10
Count:9
Count:8
Count:7
Count:6
制作后
public static void incrementCount() {
至
ppublic static synchronized void incrementCount() {
輸出:
Count:1
Count:2
Count:3
Count:4
Count:5
Count:6
Count:7
Count:8
Count:9
Count:10
在此示例中,與之前不同,我們創建了10個不同的Test
實例。
i++
盡管看起來像一條指令,但實際上是多條指令:
1+i
。 i
設置為臨時變量。 但是,假設執行i++
的線程在步驟1
之后被中斷,並且中斷線程也調用i++
。 然后,會發生這種情況:
(假設i=1
)
1+i
設置為1+i
或2
。 2
設置為i+1
,也設置為2
i
設置為臨時變量2。 現在i=2
i
設置為臨時變量1。 現在i=2
問題是,如果i++
被調用兩次,則應該為3
,而不是2
。
synchronized void
將鎖定變量i
直到整個void
完成執行。 例如:
1+i
設置為1+i
或2
。 鎖定變量i
。 i+1
,但由於變量i
的鎖定而等待 i
設置為臨時變量1。 現在i=2
。 變量i
現已解鎖。 i
已經解鎖,因此它將臨時變量2設置為i+1
,即3
。 i
設置為3
,這是預期行為。 synchronized void
本質上是暫時鎖定變量,以避免混淆程序的執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.