我有简单的问题,但有问题可以找到答案。
问题是,如果synchronized方法等于synchronized(this) - 意味着执行相同的锁定。
我想编写线程安全的代码,减少线程锁定(不想使用始终同步的方法,但有时只使用部分同步关键部分)。
如果这段代码是否相同,你可以解释一下吗?为什么用简短的话来说(简化例子来说明原子问题)?
此混合锁定代码是否等于下面的强力代码:
public class SynchroMixed {
int counter = 0;
synchronized void writer() {
// some not locked code
int newCounter = counter + 1;
// critical section
synchronized(this) {
counter = newCounter;
}
}
synchronized int reader() {
return counter;
}
}
暴力代码(每个方法都被锁定,包括非关键部分:
public class SynchroSame {
int counter = 0;
synchronized void writer() {
int newCounter = counter + 1;
counter = newCounter;
}
synchronized int reader() {
return counter;
}
}
或者我应该写这段代码(这肯定是有效但更微观的编码和不清楚)。
public class SynchroMicro {
int counter = 0;
void writer() {
// some not locked code
int newCounter = counter + 1;
// critical section
synchronized(this) {
counter = newCounter;
}
}
int reader() {
synchronized (this) {
return counter;
}
}
}
答案 0 :(得分:3)
synchronized
方法和synchronized(this)
意味着绝对相同,并使用相同的互斥锁。这是一个更喜欢品味的问题。
我个人更喜欢synchronized(this)
,因为它明确指定互斥锁的范围,它可能小于整个方法
答案 1 :(得分:2)
synchronized(this)
方法中的synchronized
肯定没有意义,因为输入方法已隐式synchronized(this)
。
由于您明确打算缩小关键部分的范围,这只是一个语法错误,但缩小范围会在您的代码中引入数据争用:您必须读取和< em>在同一synchronized
块中写共享变量。
此外,即使方法仅读取共享变量,仍然必须在synchronized
块中执行此操作;否则它可能永远不会观察到其他线程的任何写入。这是Java内存模型的基本语义。
现在,如果您展示的内容确实代表了您的完整问题,那么您甚至不应该使用synchronized
,而应使用简单的AtomicInteger
,它将具有最佳的并发性能。< / p>
答案 2 :(得分:2)
这三个例子都是等价的。在方法上使用synchronized
与在synchronized(this) {}
内包装整个正文相同。
然后,通过对某些语句使用synchronized(this) {}
,线程只重新获取它已经拥有的锁:这里没有意义。
答案 3 :(得分:2)
从功能的角度来看,同步方法和块绝对相似。它们都执行相同的任务,即避免同时访问方法中的特定方法或代码块。
当你有一个很长的方法并且只需要一部分同步时,synchronized()块更灵活,更方便。您无需锁定对整个方法的访问权限,因为我们知道同步存在一些与之相关的性能问题。因此,始终建议同步只需要部分代码而不是整个方法(如果不需要)。