[英]Synchronized objects accessed from unsynchronized methods
Suppose I have a class in which there is a StringBuffer declared as a member variable. 假设我有一个类,其中有一个StringBuffer声明为成员变量。 Two threads are trying to manipulate the object like below
两个线程试图像下面那样操纵对象
public class SomeService {
private StringBuffer sb = new StringBuffer();
public void printName(String name) {
sb.append(name);
System.out.println(sb);
}
}
public class StringBufferSynchronizationTest implements Runnable {
private SomeService service = new SomeService();
public StringBufferSynchronizationTest() {
Thread thread = new Thread(this);
thread.start();
}
public static void main(String[] args) {
new StringBufferSynchronizationTest().service.printName("oops");
}
@Override
public void run() {
service.printName("java");
}
}
And I get this output 我得到了这个输出
oopsjava
oopsjava
I thought I will get 我以为我会得到
oops
oopsjava
as output. 作为输出。 When I synchronized printName method I got the second output.
当我同步printName方法时,我得到了第二个输出。
So I understood that even I use a synchronized class I have to synchronize blocks/methods that use the synchronized classes. 所以我明白,即使我使用同步类,我也必须同步使用synchronized类的块/方法。 Am I right?
我对吗?
StringBuffer guarantees that only one thread can enter append or any other method of the same instance. StringBuffer保证只有一个线程可以输入append或同一实例的任何其他方法。 But this is all, there are no more guarantees.
但这就是全部,没有更多的保证。
Yes, the StringBuffer is synchronized, If you want the expected result, synchronized also the function printName. 是的,StringBuffer是同步的,如果你想要预期的结果,也同步函数printName。 Context switch can be occur between
sb.append(name);
sb.append(name);
之间可以发生上下文切换sb.append(name);
and System.out.println(sb);
和
System.out.println(sb);
especially it is related to slow IO. 特别是它与缓慢的IO有关。
public synchronized void printName(String name) {
sb.append(name);
System.out.println(sb);
}
It depends on what you are trying to accomplish. 这取决于你想要完成什么。
Let us take a look at printName
我们来看看
printName
public void printName(String name) {
sb.append(name);
System.out.println(sb);
}
Since sb in synchronized, sb.append(name)
has only 1 thread operating on the objects mutable state. 由于sb在synchronized中,
sb.append(name)
只有1个线程在对象上运行可变状态。 This prevents Strings, in your example, of the values 这可以防止在您的示例中使用值的字符串
oojavaps
ojopsava
and so on. 等等。 However since your printName method is not synchronized you have no guarantees on the order of invocation of the 2 methods within printName across 2 threads.
但是,由于您的printName方法未同步,因此无法保证在2个线程中调用printName中的2个方法的顺序。
The easiest way to understand it is probably to come up with the sequence of execution that results in the output 理解它的最简单方法可能是提出导致输出的执行顺序
oopsjava
oopsjava
Initially sb
is the empty String 最初
sb
是空字符串
Assume the main thread executes sb.append(name)
, leaving sb
with oops
, however it is preempted before it can execute the println
假设主线程执行
sb.append(name)
,将sb
留给oops
,但是在它执行println
之前它被抢占了
The constructor thread takes over and execute the entire method, first appending java
to sb
to get oopsjava
in sb
and then printing the output, to get 构造器线程接管并执行整个方法,首先追加
java
到sb
获得oopsjava
在sb
,然后打印输出,以获得
oopsjava
The main thread then executes, printing sb
to get 然后主线程执行,打印
sb
得到
oopsjava
I had one example of output here that was incorrect, @Cruncher pointed this out in the comments and I removed it. 我有一个输出示例,这是不正确的,@ Cruncher在评论中指出了这一点,我删除了它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.