Java:为什么同步在这里不起作用

标签 java multithreading

在两个线程下面的代码中,tr1 和 tr2 访问同一个 StringBuilder st。两者都调用同步方法 addRemove ,它所做的就是将一些内容附加到公共(public) StringBuilder 中,并在离开该方法之前删除该附加内容。 我使 addRemove() 方法同步,这意味着每个线程必须等待另一个线程完成。这意味着在离开该方法之前字符串生成器 st 的内容必须与“--”(在调用该方法之前)保持相同。但在实践中我们得到了这个

Thread# 0 created
Thread# 1 created
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 1:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--

这意味着即使在控件离开 addRemove() 之后,字符串“1”仍保留在 StringBuilder 中!这是为什么?毕竟,我使该方法同步了!

public class MyThread extends Thread{
public static int threadNum=0;
private int myNum=-1;
private StringBuilder st;
public MyThread(StringBuilder st){
    this.st = st;
    myNum = threadNum;
    System.out.println("Thread# "+myNum+" created");
    threadNum++;
}
    public void run(){
        for (int i = 0; i < 10; i++) {
            addRemove();
        }
    }
/**
 * Append and remove at the same time
 */
    private synchronized void addRemove(){
        st.append(myNum+"");
        try {
            Thread.sleep(Math.round(Math.random()*500));
        } catch (InterruptedException e) {
            System.err.println("Thread# "+myNum+" interupted");
        }
        st.deleteCharAt(st.length()-1);
        System.out.println("Thread# "+myNum+":"+st);
    }

    public static void main(String[] args) {
        StringBuilder st= new StringBuilder("--");
        MyThread tr0= new MyThread(st);
        MyThread tr1= new MyThread(st);
        tr0.start();
        tr1.start();
    }

}

最佳答案

您正在以默认方式进行同步,这意味着该方法正在当前实例的对象 this 对象上进行同步,并且由于每个线程都是其自己的唯一对象,因此每个实例都会锁定自身。如果您希望同步工作,那么该方法应该由一个对象同步,也许是一个专门为此目的创建的静态对象。

public static final Object myLock = new Object;

synchronize(myLock) {
  // ....
}

关于Java:为什么同步在这里不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24576400/

相关文章:

java - 交换器 : JVM never stops

java - 没有主键 ID 的实体

java - 计算我的数据和当前数据之间的秒数

java - .net<->Java 文本编码在开发环境中有效,但在 "production"处失败

c# - 我应该将 await 与 async Action 方法一起使用吗?

c++ - (C++ 线程): Creating worker threads that will be listening to jobs and executing them concurrently when wanted

java - Spring Boot - JPA - Postgres 错误 : cross-database references are not implemented:

java - 使用链接队列出列方法错误无法将对象转换为类

ruby-on-rails - 在 ruby​​ 中通过并行处理有序插入数据

c++ - 在 Windows 中更改 boost 线程优先级