我对synchronized
关键字的用法和重要性有一些疑问。
synchronized
关键字的意义是什么? synchronized
方法? synchronized
关键字是关于读取和写入相同变量,对象和资源的不同线程。这不是 Java 中的一个简单主题,但这里引用了 Sun:
synchronized
方法启用了一个简单的策略来防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的。
简而言之:如果有两个线程正在读取和写入相同的 “资源”,比如名为foo
的变量,则需要确保这些线程以原子方式访问变量。如果没有synchronized
关键字,您的线程 1 可能看不到更改线程 2 对foo
,或者更糟糕的是,它可能只有一半更改。这不是你逻辑上所期望的。
同样,这是 Java 中的一个非平凡的主题。要了解更多信息,请在此处探索有关 SO 和 Interwebs 的主题:
继续探索这些主题,直到名称“Brian Goetz”与您大脑中的“并发”一词永久相关。
好吧,我认为我们有足够的理论解释,所以请考虑这个代码
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
所有线程都可以同时访问此方法。
当一个线程调用对象的 synchronized 方法'test' 时(这里的对象是'TheDemo' 类的实例)它获取该对象的锁,任何新线程都不能调用相同对象的 ANY synchronized 方法,只要前一个线程获得锁的人不会释放锁。
当调用类的任何静态同步方法时,会发生类似的事情。线程获取与类关联的锁(在这种情况下,任何线程都可以调用该类实例的任何非静态同步方法,因为该对象级锁仍然可用)。只要当前持有锁的线程没有释放类级别锁,任何其他线程将无法调用该类的任何静态同步方法。
输出同步
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
synchronized
关键字可防止多个线程对代码块或对象的并发访问。默认情况下, Hashtable
是synchronized
,因此一次只能有一个线程访问该表。
在使用像HashMap
这样的non-synchronized
构造时,必须在代码中构建线程安全功能以防止内存一致性错误。