Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么“synchronized”对于变量是非法的?_Java_Variables_Synchronized - Fatal编程技术网

Java 为什么“synchronized”对于变量是非法的?

Java 为什么“synchronized”对于变量是非法的?,java,variables,synchronized,Java,Variables,Synchronized,这是一个非常简单的问题,但我无法理解其背后的想法: 为什么synchronized不能分配给Java变量 它只能指定给方法和块。 我个人认为这对Java编程语言来说是一个非常好的补充。他们有这个关键词。对你没有帮助。您可以使用synchronized使代码块成为原子代码。因此,在大多数情况下,需要同步的代码行不止一行。同步的代码块保护完整的代码块。方法上的同步保护方法的完整代码。在这两种情况下,synchronized指的是它用作监视器的对象—this(或当前类对象)或指定的对象 第一:对监视器

这是一个非常简单的问题,但我无法理解其背后的想法:

为什么
synchronized
不能分配给Java变量

它只能指定给方法和块。
我个人认为这对Java编程语言来说是一个非常好的补充。

他们有这个关键词。

对你没有帮助。您可以使用synchronized使代码块成为原子代码。因此,在大多数情况下,需要同步的代码行不止一行。

同步的代码块保护完整的代码块。方法上的同步保护方法的完整代码。在这两种情况下,synchronized指的是它用作监视器的对象—this(或当前类对象)或指定的对象

第一:对监视器对象的要求意味着同步字段不能是基元类型

第二:场上的同步服务器应该做什么

有两种可能的答案:

  • 保护对引用本身XOR的访问
  • 保护对引用后面对象的访问
选项一将是一个鸡蛋问题:为了保护访问,必须首先访问字段。尝试在多处理器上以原子方式执行此操作可能会很有趣。此外:如果访问是写入(即对象更改),则监视器将位于第一个对象上,而第二个对象已安装。。。疯狂就在这条路上

选项二:请参见以下代码:

public class Foo {
     public synchronized StringBuilder sb = ...;
     public void doSomething1(){
         StringBuilder sb = this.sb;
         sb.append("foo");
     }

     public void doSomething2(){
         this.sb.append("foo");
     }
}
因为只有访问会受到保护,所以这两种方法的作用是相同的。第一个版本只是让它更清楚一点,
append
调用本身不受保护

哦,我忘了:在这两种情况下,您只能使用synchronized的互斥功能,
wait
notify
功能将不可用,因为您无法将任何代码附加到变量

剩下的是:

也许只是原子参考的快捷方式



这是一个非常罕见的用例,因此更改语言本身不是一个好的选择。

如果您正在寻找原子行为的字段,请尝试
java.util.concurrent.atomic
类。例如,
AtomicInteger
允许您以原子方式向其添加数字。如果对象分配是一个问题,并且您确定自己需要它,
AtomicIntegerFieldDupDater
(及其同类产品)可以让您像原子一样访问
volatile
字段,但您必须小心,因为使用这种方法很容易破坏代码。

在变量上设置时,您希望它实际做什么?您应该将对字段的访问包装为(可能是同步的)getter和setter,对吗?;-)wjat您希望通过
synchronized
实现什么?而且
synchronized
确实需要一个对象(监视器)@JoachimIsaksson轻松自动原子访问。:)@Michael,定义
原子的
,b/c我想你实际上并不是指
原子的
,我想你经常只是想访问一个变量原子的。@Michael:有原子引用或
volatile
关键字。@Michael,除非32位上的
long/double
,否则所有变量都是原子变量,您希望处理一个变量,但要处理多行代码。因此,您必须同步整个代码块。否则,您可能会遇到与其他线程的争用情况。@bestsss:atomic,因为在其他线程中无法看到“半写值”。但这并不意味着其他线程可以看到更改。但不涉及监视器,尽管我想另一种选择是,如果
sb
同步的
,那么使用它的任何方法都会在整个方法块的
sb
上隐式同步。因此,在您的示例中,
doSomething2()
相当于
doSomething2(){synchronized(sb){this.sb.append(“foo”);}
。将该想法归档到“实现死锁的非常非常简单的方法”下。@yshavit:您的想法的一个注释:由于
sb
是公共的,这意味着从另一个类访问
sb
将需要该另一个类中的额外代码。现在想象一下,我们的
sb
类发生了变化:它添加或删除了
synchronize
,但第二个类没有重新编译。。。这是对封装的又一次打击。是的,但是您可以说
synchronized
-包装只发生在声明成员的类中。这将允许其他类破坏您的原子性,但这就是提供需要同步访问的引用所得到的结果。如果你有
公共StringBuidler sb;私有最终对象锁=新对象()
具有一个不变量,
sb
总是在
同步(锁)
中访问。顺便说一句,另一个可能(但不是很有帮助)的选择是让
同步sb
意味着任何使用
sb
的方法(在类中)都是在
上同步的。但是今天已经结束了,我在等公共汽车。:)@伊莎维特:我明白,我不想变得粗鲁或诸如此类。你的想法是正确的。我只是想探索一些含义。希望你能赶上公共汽车:-)