Java锁定(同步)全局变量

时间:2015-09-01 10:07:14

标签: java

我有一个代码

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
...

5 个答案:

答案 0 :(得分:1)

在开始第二个线程之前(或者在启动它之后,但在进入for循环之前),您可以调用t.join(),它将阻塞,直到t完成。

答案 1 :(得分:1)

简单的解决方案是将start()更改为run(),因为您实际上并不想要多个线程。

但是你可以使用这个

synchronized(Exec.class) {

synchronized(System.out) {

作为共享的全局对象,或者您可以传递这样的对象。

答案 2 :(得分:0)

只需创建一个锁变量并锁定此变量。

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();
                    }
                }
            }
        }
    }
}

答案 3 :(得分:0)

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();
                }
            }
            }
        }
    }
}

答案 4 :(得分:0)

虽然当您想要按顺序执行代码块时使用多线程没有意义,但如果您需要它,您仍可以通过多种方式解决此问题。您可以使用锁定机制(内部,外部,任何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循环以保持等待。完成第一个线程后,它会将boolean设置为true,其他线程也会看到此更改,因为lock是不稳定的。