简体   繁体   English

从非同步方法访问的同步对象

[英]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 构造器线程接管并执行整个方法,首先追加javasb获得oopsjavasb ,然后打印输出,以获得

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.

相关问题 同步和非同步方法的ConcurrentModificationException - ConcurrentModificationException with synchronized and unsynchronized methods 由于未同步的同步方法,导致ConcurrentModicationException - ConcurrentModicationException due to unsynchronized synchronized methods 同步语句和单独的非同步方法 - Synchronized statements and separate unsynchronized methods 同步访问的方法是否应该同步? - Should synchronized accessed methods be synchronized? 为什么非同步对象的性能优于同步对象? - Why do unsynchronized objects perform better than synchronized ones? 通过同步方法访问的私有类参数是否被视为“同步对象”? - Is a private class parameter accessed through synchronized methods considered a 'synchronized object'? 我们可以同时从多个线程访问同一个实例的同步方法和非同步方法吗? - Can we Access Synchronized method and an unsynchronized method of same instance from multiple threads at the same time? 调用同步的静态方法,然后可以访问其他静态方法吗? - invoke synchronized static method,then can other static methods be accessed? Java内存模型:混合不同步和同步 - Java Memory Model: Mixing unsynchronized and synchronized 同步代码比非同步代码执行得更快 - Synchronized code performs faster than unsynchronized one
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM