“Synchronized”是什么意思?

问题

我对synchronized关键字的用法和意义有一些疑问。

  • synchronized 关键字的意义是什么?
  • 什么时候应该同步方法?
  • 它在编程和逻辑上意味着什么?

#1 热门回答(730 赞)

synchronized关键字是关于读取和写入相同变量,对象和资源的不同线程。这在Java中并不是一个简单的话题,但是这里是Sun的一句话:

同步方法为防止线程干扰和内存一致性错误提供了一个简单策略:如果一个对象对多个线程可见,则通过同步方法完成对该对象变量的所有读写操作。

简而言之,当你有两个线程正在读写相同的'资源'时,比如说一个名为foo的变量,你需要确保这些线程以原子方式访问变量。没有synchronized关键字,你的线程1可能看不到改变线程2对foo,或者更糟,它可能只有一半改变。这不是你逻辑上所期望的。

再次,这是Java中的一个非平凡的话题。要了解更多信息,请在此处探讨SO和Interwebs上的主题:

  • 并发
  • Java内存模型

继续探索这些话题,直到名字“Brian Goetz”与你的大脑中的术语“并发”永久关联。


#2 热门回答(239 赞)

那么,我认为我们有足够的理论解释,所以考虑这个代码

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

注意:只要前一个线程的执行没有完成,synchronized就会阻塞下一个线程对方法test()的调用。线程一次可以访问这个方法。如果没有`synchronized',所有线程都可以同时访问这个方法。

当一个线程调用对象的同步方法'test'(这里的对象是'TheDemo'类的一个实例)时,它获取该对象的锁,任何新线程只要前一个线程不能调用同一对象的任何同步方法已获得锁的锁不会释放锁。

当类的任何静态同步方法被调用时,会发生类似的事情。线程获取与类关联的锁(在这种情况下,任何线程都可以调用该类实例的任何非静态同步方法,因为该对象级锁仍然可用)。只要当前持有锁的线程没有释放类级别锁,任何其他线程将无法调用该类的任何静态同步方法。
带同步输出

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

无同步输出

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9

#3 热门回答(102 赞)

synchronized关键字阻止多个线程同时访问一段代码或对象。默认情况下,Hashtablesynchronized,所以一次只能有一个线程访问表。

在使用像HashMap这样的非同步结构时,你必须在代码中建立线程安全特性来防止内存一致性错误。