簡體   English   中英

我可以使用靜態布爾變量作為同步線程的鎖嗎?

[英]can I use static boolean variable as a lock for a synchronized thread?

我試圖使用靜態布爾變量來鎖定和解鎖兩個同步的線程。 所以我寫了下面的代碼:

public class Main {

    public static void main(String[] args){

        //MyObject lock = new MyObject();
        Thread1 t1 = new Thread1(100,'#');
        Thread1 t2 = new Thread1(100,'*');

        t1.start();
        t2.start();
    }
}

public class Thread1 extends Thread {

    public static boolean lock;
    int myNum;
    char myChar;

    public Thread1(int num, char c){
        myNum = num;
        myChar = c;
        lock = false;
    }

    public synchronized void run(){
        System.out.println(getName() + " is runing");
        while (Thread1.lock == true){
            System.out.println(getName() + " is waiting");
            try{wait();}
            catch(InterruptedException e){}
        }
        Thread1.lock = true;
        for(int i = 0; i<myNum; i++){
            if(i%10==0)
                System.out.println("");
            System.out.print(myChar);
        }
        Thread1.lock = false;
        notifyAll();
    }
}

可能我做得不對,因為只有一個線程正在打印“mychar”而另一個線程只是進入wait()並且在我執行notifyAll()時沒有醒來。 我認為這可以是一個很好的方法來為整個類使用靜態布爾變量,而不是每次更改它並調用notifyAll()來檢查其他對象中的這個標志...

輸出示例:

Thread-0 is runing

Thread-1 is runing
Thread-1 is waiting
##########
##########
##########
##########
##########
##########
##########
##########
##########
##########

為什么它不起作用

notify()wait()使用它們被調用的對象的“監視器”。 在您的情況下,就是this ,正在運行的Thread1的特定實例。

所以,當Thread-0運行時:

  • 它會檢查lock
  • 發現它是false
  • 它運行主要代碼
  • 它調用notifyAll()this (它本身, Thread-0 )。

Thread-1運行:

  • 它會檢查lock
  • 發現它是true
  • 和呼叫wait()this (它本身, Thread-1

由於Thread-0 this調用notifyAll() (它本身),並且Thread-1 this調用wait() (它本身 ),因此Thread-1正在等待一個不同於Thread-0通知的監視器,所以它從未發布過。

如果您的計划是讓代碼按順序運行,請使用:

public class Thread1 extends Thread {

    private static final Object lock = new Object();

    public void run(){
        // non-sequential code
        System.out.println(getName() + " is running");
        synchronized (lock) {
            // this code will be run sequentially by one thread at a time
        }
        // non-sequential code
    }
}

對不起,但這提供了負值,因為它沒有任何保證,只會給人一種安全感。 這有幾個問題:

  1. 該變量是非易失性的,因為來自一個線程的更改可能對另一個不可見。
  2. 你的鎖定不是原子的。 因此,可能發生的是兩個線程都可以傳遞while循環,然后將boolean都設置為true。
  3. notifyAll()喚醒等待對象實例的所有線程。 由於每個線程都在等待自己作為監視器,因此它們不會被喚醒。

Java中有很多好的鎖定機制 - 嘗試並發包中的那些(雖然在你的情況下,一個簡單的同步塊就足夠了)。 如果你堅持使用布爾值來鎖定,你需要:

  1. 作為信號AtomicBoolean一個靜態的最終 AtomicBoolean (只要你不改變它並保證可見性,非final就可以了)
  2. 使用compareAndSet作為循環/鎖定條件,以便訪問是原子的。
  3. AtomicBooleanWait() ,以便線程共享它們正在等待的監視器(以及它上面的notifyAll() )。

您可以使用更簡單的方法來同步線程。

class Thread1 extends Thread {

    private static final Object lock = new Object();
    int myNum;
    char myChar;

    public Thread1(int num, char c){
        myNum = num;
        myChar = c;
    }

    public void run(){
        System.out.println(getName() + " is runing");
        synchronized(lock) {
            for(int i = 0; i<myNum; i++){
                if(i%10==0)
                    System.out.println("");
                System.out.print(myChar);
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM