java - 两个进程临界区错误解决方案

标签 java multithreading operating-system critical-section

我已将两个进程关键部分解决方案应用于两个线程而不是进程。我的代码是:

class Main
{
static boolean flag[];
static int turn;
static int count;
synchronized static void print(char ch,int n)
{
    int i;
    System.out.println(ch);

    for(i=0;i<n;i++){
        System.out.println(i);

    }
}

public static void main(String[] args) throws IOException
{
        flag = new boolean[2];
        flag[0] = flag[1] = false;
        turn = 0;
        count = 0;
        ThreadLevelOne t1 = new ThreadLevelOne('a');
        ThreadLevelTwo t2 = new ThreadLevelTwo('b');
        t1.start();
        t2.start();
}

static class ThreadLevelOne extends Thread{
    private char ch;

    public ThreadLevelOne(char ch){
        this.ch = ch;
    }

    public void run(){
        while(true)
        {
            flag[0] = true;
            turn = 1;
            while(flag[1] && turn == 1);
            print(ch,3);    
            count++;
            System.out.println("Counter is : " + count);
            flag[0] = false;
        }

    }
}

static class ThreadLevelTwo extends Thread{
    private char ch;

    public ThreadLevelTwo(char ch){
        this.ch = ch;
    }

    public void run()
    {
        while(true)
        {
            flag[1] = true;
            turn = 0;
            while(flag[0] && turn == 0);
            print( ch, 4);
            count++;
            System.out.println("Counter is : " + count);
            flag[1] = false;

        }

    }
}
}

执行上述代码时,它不会无限运行,而是在每次执行时在任意计数器值处停止。这是两进程解决方案对线程的有效应用吗?如果是,那么为什么程序在任意计数器值处停止?如果不是,那么如何在线程中实现这一点?

在codeBlind回答后编辑:

输出:程序执行在此阶段停止 Program execution halts at this stage

即使我不增加计数器值,程序也会在一定时间后停止

最佳答案

您是并发执行非原子操作(特别是count++)以及在每个线程中使用标志的方式的受害者。但为了简单起见,我们来谈谈 count++++ 运算符实际上执行三个命令,每个命令都有自己的时钟周期:

  1. 读取计数的值
  2. 1 添加到从 count 检索到的值
  3. 将新值存储到count

您看到的问题是这些命令在两个线程之间交错造成的。当线程 B 尝试读取新的 count 值时,线程 A 可能尚未存储该值。

一个快速修复方法是使用 AtomicInteger 进行计数,而不是原始 int - AtomicInteger 保证整数操作的线程安全。

编辑

此代码中还存在其他竞争条件。每个线程的 while 循环参数(例如 flag[0] &&turn == 0)都是非原子的,但两个线程都能够修改 turn。您留下了这样一种可能性:一个线程可能会在另一个线程的 while 参数完全计算之前设置轮次,从而导致您的线程陷入死锁。

如果您只想保证每个线程都不能位于 while 循环内,而另一个线程则位于 while 循环内,那么您应该将每个 while 循环编写为如下所示:

while(true){
    synchronized(Main.class){
        print( ch, 4);
        count++;
        System.out.println("Counter is : " + count);
    }
}

如果您想保证每个线程必须“轮流”,您应该考虑使用 wait()notify()

关于java - 两个进程临界区错误解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36432922/

相关文章:

java - 如何在 JRadioButtons 的 ButtonGroup 中随机选择一个按钮?

java - 我不明白如何在线程上使用等待和通知

memory - 分页怎么有内部碎片没有外部碎片?

java - 将自定义 keystore 与 Jetty 的 WebSocketClientFactory 结合使用

java - 如何使用 android 将我录制的音频上传到 dropbox?

java - 如果我使用 FileReader 读取文件,我怎么知道我在文件中的位置?

multithreading - F# 事件的线程安全引发

c# - 在打开表单之前使用 Invoke 时出现 InvalidOperationException

blocking - 通俗易懂的操作系统概念

operating-system - 什么是调度程序延迟?