java - 什么时候应该声明一个方法是同步的?
问题描述
以下是一个简单的工作程序,它使用两个线程来打印一个计数器:
public class SynchronizedCounter implements Runnable {
private static int i = 0;
public void increment() { i++; }
public int getValue() { return i; }
@Override
public void run() {
for( int i = 0; i < 5; i++ ) {
synchronized( this ) {
increment();
System.out.println( Thread.currentThread().getName() + " counter: " + this.getValue() );
}
}
}
public static void main( String[] args ) {
ExecutorService executorService = Executors.newFixedThreadPool( 2 );
SynchronizedCounter synchronizedCounter = new SynchronizedCounter();
executorService.submit( synchronizedCounter );
executorService.submit( synchronizedCounter );
executorService.shutdown();
}
}
输出如预期 - 两个线程按顺序显示计数器。
如果increment()
和getValue()
被声明为synchronized
和synchronized
块代码被注释,输出显示可见性和竞争问题。
As increment()
and getValue()
are not declared as and by, 只是,如果可以实现同步,则synchronized
使用块(传递监视器对象),在什么情况下应将它们声明为?synchronized
synchronized
解决方案
当您需要方法主体周围的同步块的语义时,声明方法同步。
synchronized void increment() {
...
}
与以下内容完全相同:
void increment() {
synchronized (this) { ... }
}
在上面的代码中这样做的事情是您不再以原子方式执行increment()
andgetValue()
方法:另一个线程可以在线程调用之间插入并执行方法:
Thread 1 Thread 2
increment()
increment()
getValue()
getValue()
这是可能的,但是两个线程不能同时执行increment()
(或getValue()
),因为它们是同步的(*)。
另一方面,在问题中的代码中同步调用意味着这两个调用是原子执行的,因此两个线程不能交错:
Thread 1 Thread 2
increment()
getValue()
increment()
getValue()
(*) 实际上,它们可以同时执行该方法。只是除了一个线程之外的所有线程都将在synchronized (this)
.
推荐阅读
- python - Python查找数组的所有子数组,长度大于1
- react-native - 表单输入中的文本组件
- python-3.x - python中指向lambda函数的指针
- php - Laravel 多重删除
- jquery - 将变量从 1 个事件处理程序传递到另一个
- jenkins-pipeline - 无法从 Jenkins Pipeline 将图像推送到 GCR
- vue.js - 试图将多个条件放在一个循环 vue.js 中
- javascript - 可共享模块的打字稿层次结构
- spring - :无法解析匹配的构造函数(提示:为简单参数指定索引/类型/名称参数以避免类型歧义)
- java - JXLS Transformer 对象未初始化