簡體   English   中英

Java鎖定(同步)全局變量

[英]Java lock (synchronize) global variable

我有一個密碼

public class Exec {

    private String string = "";

    public void start() {
        MyThread t = new MyThread();
        MyThread2 t2 = new MyThread2();
        t.start();
        t2.start();
    }

    private class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {

                string = "1";

                System.out.println(string);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private class MyThread2 extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {

                string = "2";

                System.out.println(string);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

這沒什么難的。 2個線程打印一個值。

輸出:

1
2
1
2
1
...

問題我如何鎖定全局變量(資源)? 輸出:

1
1
1
1
...
2
2
2
2
...

在啟動第二個線程之前(或在啟動之后,但進入for循環之前),您可以調用t.join() ,它將阻塞直到完成t

簡單的解決方案是將start()更改為run()因為您實際上不需要多個線程。

但是你可以使用這個

synchronized(Exec.class) {

要么

synchronized(System.out) {

作為共享的全局對象,也可以傳遞此類對象。

只需創建一個鎖變量並鎖定該變量即可。

public class Exec {

    private String string = "";
    private Object globalLock = new Object();  // The global lock  

    public void start() {
        MyThread t = new MyThread(globalLock);
        MyThread2 t2 = new MyThread2(globalLock);
        t.start();
        t2.start();
    }

    private class MyThread extends Thread {
        private Object lock;

        public MyThread(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized(lock) {
                for (int i = 0; i < 10; i++) {
                    string = "1";
                    System.out.println(string);
                    try {
                        sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private class MyThread2 extends Thread {
        private Object lock;

        public MyThread2(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized(lock) {
                for (int i = 0; i < 10; i++) {
                    string = "2";
                    System.out.println(string);
                    try {
                        sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
class Exec{
private String string = "";
Object lock = new Object();
    public void start() {
        MyThread t = new MyThread();
        MyThread2 t2 = new MyThread2();
        t.start();
        t2.start();
    }

    public static void main(String[] args) {
        new MyServer().start();
    }

    private class MyThread extends Thread {
        @Override
        public void run() {
            synchronized (lock) {


            for (int i = 0; i < 10; i++) {

                string = "1";

                System.out.println(string);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            }
        }


    }

    private class MyThread2 extends Thread {
        @Override
        public void run() {
            synchronized (lock) {


            for (int i = 0; i < 10; i++) {

                string = "2";

                System.out.println(string);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            }
        }
    }
}

雖然當您要順序執行代碼塊時使用多線程沒有意義,但是仍然可以通過多種方式解決此問題。 您可以使用鎖定機制(內部,外部,任何Lock接口實現等),同步器等。IMO最簡單的方法是使用volatile變量:

public class Exec{
    private volatile boolean lock = false;

    private String string = "";

    public void start() {
        MyThread t = new MyThread();
        MyThread2 t2 = new MyThread2();
        lockResource();
        t.start();
        t2.start();
    }

    void lockResource() {
        lock = true;
    }

    void releaseResource() {
        lock = false;
    }

    private class MyThread extends Thread {
        @Override
        public void run() {
            while (!lock) ;
            for (int i = 0; i < 10; i++) {
                string = "1";

                System.out.println(string);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            releaseResource();
        }
    }

    private class MyThread2 extends Thread {
        @Override
        public void run() {
            while (lock) ;
            for (int i = 0; i < 10; i++) {
                string = "2";
                System.out.println(string);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

由於布爾變量lock為false,因此第一個線程將繼續打印,而其他線程具有while循環以保持等待狀態。 一旦第一個線程完成,它將布爾值設置為true,並且由於lock是易失的,其他線程也將看到此更改。

暫無
暫無

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

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