Java中非final对象同步的正确方法
我想用锁保护一个物体 我没有选择互斥体,因为“try..catch”的语法很难看 浏览stackoverflow,我得出结论,这就是如何正确实现我的目标:Java中非final对象同步的正确方法,java,concurrency,thread-safety,Java,Concurrency,Thread Safety,我想用锁保护一个物体 我没有选择互斥体,因为“try..catch”的语法很难看 浏览stackoverflow,我得出结论,这就是如何正确实现我的目标: class MyClass { private final Object lock = new Object(); private Channel channel = null; public void setChannel() { synchronized (lock) {
class MyClass {
private final Object lock = new Object();
private Channel channel = null;
public void setChannel() {
synchronized (lock) {
channel = new Channel();
synchronized (channel) {
// setup channel
}
}
}
public void unsetChannel() {
synchronized (lock) {
synchronized (channel) {
channel.close();
}
channel = null;
}
}
public boolean isSet() {
synchronized (lock) {
if (channel == null)
return false;
synchronized (channel) {
return channel.isActive();
}
}
}
}
但是它看起来很难看而且很难读
如何提高解决方案的可读性?您可以简化锁定策略:
class MyClass {
private final Object lock = new Object();
private Channel channel = null;
public void setChannel() {
// other code can go here
synchronized (lock) {
channel = new Channel();
// setup channel
}
// other code can go here
}
public void unsetChannel() {
// other code can go here
synchronized (lock) {
channel.close();
channel = null;
}
// other code can go here
}
public boolean isSet() {
synchronized (lock) {
if (channel == null) {
return false;
}
return channel.isActive();
}
}
}
实际上,lock
对象保护对通道变量的任何访问
编辑以显示未与
频道
交互的其他代码可能位于锁定之外的位置。您可以简化锁定策略:
class MyClass {
private final Object lock = new Object();
private Channel channel = null;
public void setChannel() {
// other code can go here
synchronized (lock) {
channel = new Channel();
// setup channel
}
// other code can go here
}
public void unsetChannel() {
// other code can go here
synchronized (lock) {
channel.close();
channel = null;
}
// other code can go here
}
public boolean isSet() {
synchronized (lock) {
if (channel == null) {
return false;
}
return channel.isActive();
}
}
}
实际上,lock
对象保护对通道变量的任何访问
编辑以显示未与
频道
交互的其他代码可能位于锁之外的位置。锁上的外部锁保护所有内容。你不需要第二把锁。当外部锁保持不动时,第二个线程永远无法到达它。锁上的外部锁保护一切。你不需要第二把锁。当外部锁保持时,第二个线程永远无法到达它。为什么要锁定新创建的对象?也可以同步整个过程method@ScaryWombat我想在使用之前对创建的对象进行设置。我不应该这样做吗?我不想同步整个方法,因为我为simplisity的sakeInsetChannel
清理了方法的代码,因为它已经被锁定,所以再次锁定没有意义。如果isSet()
真的在lock
上同步,那么,可怕的袋熊是对的,没有理由在频道上同步,因为锁定
上的锁定已经会阻止任何其他代码到达它试图访问频道
的点。我想你可以通过将频道
声明为易失性
,获得同样的效果,而不是在上面同步。你的链接上的人似乎说你必须声明所有实例字段为volatile,但我认为这是不对的——只有那些需要的字段才是。如果有多个线程可能正在访问同一个字段(有些可能是写入),那么它应该是易变的。为什么要锁定新创建的对象?也可以同步整个过程method@ScaryWombat我想在使用之前对创建的对象进行设置。我不应该这样做吗?我不想同步整个方法,因为我为simplisity的sakeInsetChannel
清理了方法的代码,因为它已经被锁定,所以再次锁定没有意义。如果isSet()
真的在lock
上同步,那么,可怕的袋熊是对的,没有理由在频道上同步,因为锁定
上的锁定已经会阻止任何其他代码到达它试图访问频道
的点。我想你可以通过将频道
声明为易失性
,获得同样的效果,而不是在上面同步。你的链接上的人似乎说你必须声明所有实例字段为volatile,但我认为这是不对的——只有那些需要的字段才是。如果您遇到多个线程可能正在访问同一字段的情况(有些线程可能是写的),那么它应该是不稳定的。那么我应该相信谁呢?:)这仅适用于锁定对象为非最终对象的情况。在我的示例中,我锁定了最后一个对象lock
。我想保护非最终的“通道”对象,那么您的解决方案是否符合条件?如果您将对通道
对象的每次访问都像我上面所说的那样使用锁进行包装,那么解决方案将起作用。那个家伙说您应该在受保护的对象上进行同步“为了RAM同步”。那么我应该相信谁呢?:)这仅适用于锁定对象为非最终对象的情况。在我的示例中,我锁定了最后一个对象lock
。我想保护非最终的“通道”对象,那么您的解决方案是否符合条件?如果您将对通道
对象的每次访问都像我上面所说的那样使用锁进行包装,那么解决方案将起作用。那个家伙说您应该在受保护的对象上进行同步“为了RAM同步”。一个锁真的足够了吗?那个家伙说你应该在受保护的对象上同步“为了RAM同步”。一把锁就够了吗?