Java线程: synchronized reading and writing of value on the same object

标签 java multithreading synchronization

我对这个关于线程的任务有点困惑:我有三个类:

  • 存储整数的类,我们称之为StoredInteger
  • 一个 Thread 类 (IncrementThread),用于递增 StoredInteger 类的整数值
  • 另一个线程类 (ReadThread),应该从 StredInteger 类读取整数值

该过程应该以输出应该同步的方式进行,例如:

  • IncementThread 将值 1 写入 StoredInteger
  • ReadThreadStoredInteger 读取值 1
  • IncementThread 将值 2 写入 StoredInteger
  • ReadThreadStoredInteger 读取值 2 ...等等

我遇到的问题是 ReadThread 等待 IncrementThread 完成,然后它只读取最后一个值。这是我的一些代码:

public class ReadThread extends Thread {

    private StoredInteger stored_integer;
    ...

    @Override
    public void run()
    {
        int i = 0;
        while(i < 100)
        {
            synchronized(this.getStoredInteger())
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    ...
                }
                System.out.format("%s: Reading %d from StoredInteger\n", this.getClass().getSimpleName(), this.getStoredInteger().getValue());
                i++;
            }

        }
    }

   ...
}

.

public class IncrementThread extends Thread {

private StoredInteger stored_integer;

    ...

    @Override
    public void run()
    {
        int i = 0;
        while(i < 100)
        {
            synchronized(this.getStoredInteger())
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                   ...
                }
                System.out.format("%s: Writing %d to StoredInteger\n", this.getClass().getSimpleName(), i);
                this.getStoredInteger().setValue(i);
                i++;
            }          
        }
    }
    ...
}

以及正在运行的线程:

public static void main(String[] args) throws InterruptedException
    {
        StoredInteger intgr = new StoredInteger();
        Thread write = new Thread(new IncrementThread(intgr));
        Thread read = new Thread(new ReadThread(intgr));
        write.start();
        read.start();
        write.join();
        read.join();

    }

我在这里做错了什么?

谢谢!

最佳答案

代码中没有任何内容可以保证读/写线程交替工作。基本上,两个线程都进入互斥区域。他们在那里等待 1 秒(保持锁定)并写入或读取一个值。您可以在互斥体区域之外进行 sleep ,但同样,它不能保证线程会交替工作(尽管使用 1 秒的 sleep() 几乎可以肯定它们会交替工作)。

@Override
public void run() {
    int i = 0;
    while (i < 100) {
        synchronized (stored_integer) {
            System.out.format("%s: Writing %d to StoredInteger\n", this.getClass().getSimpleName(), i);
            stored_integer.value = i;
            i++;
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            //
        }
    }
}

@Override
public void run() {
    int i = 0;
    while (i < 100) {
        synchronized (stored_integer) {
            System.out.format("%s: Reading %d from StoredInteger\n", this.getClass().getSimpleName(), stored_integer.value);
            i++;
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }
    }
}

但是,要正确执行此操作,您需要使用 wait() 和 notification() 方法。让写入器线程在写入后等待,以便读取器线程可以读取并唤醒写入器。像这样的事情:

@Override
public void run() {
    int i = 0;
    while (i < 100) {
        synchronized (stored_integer) {
            System.out.format("%s: Writing %d to StoredInteger\n", this.getClass().getSimpleName(), i);
            stored_integer.value = i;
            i++;

            // Writer wakes up writer
            stored_integer.notify();

            // Writer waits until it can read
            try {
                stored_integer.wait();
            } catch (InterruptedException ex) {
                //
            }
        }
    }
}

@Override
public void run() {
    synchronized (stored_integer) {
        // Reader waits for the first time!
        try {
            stored_integer.wait();
        } catch (InterruptedException ex) {
            //
        }
    }
    int i = 0;
    while (i < 100) {
        synchronized (stored_integer) {

            System.out.format("%s: Reading %d from StoredInteger\n", this.getClass().getSimpleName(), stored_integer.value);
            i++;

            // Reader wakes up writer
            stored_integer.notify();

            // If there are still more values to read
            if (i < 100) {
                // Reader waits until it can read
                try {
                    stored_integer.wait();
                } catch (InterruptedException ex) {
                    //
                }
            }
        }
    }
}

在主线程上,首先在读取器线程上使用 start(),然后才在写入器线程上使用 start()。即使这样,代码也可能无法工作。如果您的处理器不应该在编写器执行 Notify() 之前等待读取器(这可能会发生,因为毕竟这些是线程),那么您将陷入死锁。解决这个问题的一种方法是使用一个条件变量,它会在其中等待(如果需要),并且仅在读取器被阻塞等待后才启动写入器线程。

关于Java线程: synchronized reading and writing of value on the same object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24520129/

相关文章:

Java多线程同步

java - 可以在 Tomcat 上部署 WAR 后更改 JAR 文件吗?

java - JLayer 总是抛出 ArrayIndexOutOfBounds 异常

c++ - posix 线程同步停止在同一代码

C#,我怎么知道我的所有线程何时完成?

Java 静态和非静态方法的同步

c++ - 没有 mutex.h 的 VC++ 中的自旋锁同步

java - 运行时异常 : Buffer not large enough for pixels

java - 基于多个标志的条件

c++ - 如何并行化将矩阵的行随机复制到内存中的另一个矩阵的过程?