Semaphore Question: 从并行线程中访问线程变量

huangapple go评论73阅读模式
英文:

Semaphore Question: Accessing Thread Variable From A Parallel Thread

问题

我正在尝试理解Java中的信号量(Semaphores),并且我想使用并行线程来同时生成数组中的数字并对该数据执行操作,而不更改数组本身,以避免竞争条件。在第一个线程中生成数字相对简单,如果程序按顺序工作,获取生成后的数据也不会太难。然而,我不太明白如何在正在生成数据的另一个线程中访问该数组。我知道信号量用于控制对共享数据结构的访问,类似于互斥锁,但对我来说不清楚如何以合法的方式声明(在这种情况下是数组)。

以下是一个基本示例:

import java.util.concurrent.Semaphore;
import java.util.Random;

public class Main {
    static Semaphore semaphore = new Semaphore(2);

    static class Thread1 extends Thread {
        private int[] randArray = new int[50];

        public void run() {
            try {
                Random rng = new Random();
                semaphore.acquire();

                try {
                    for (int i = 0; i < 50; i++) {
                        randArray[i] = rng.nextInt() % 100;
                        System.out.println("Random number " + i + " : " + randArray[i]);

                        Thread.sleep(2000);
                    }
                } finally {
                    semaphore.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class Thread2 extends Thread {

        public void run() {
            try {
                semaphore.acquire();
                try {
                    for (int i = 0; i < 50; i++) {
                        // 使用Thread1生成的数组进行计算

                        Thread.sleep(2000);
                    }
                } finally {
                    semaphore.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Thread1 t1 = new Thread1();
        t1.start();
        Thread2 t2 = new Thread2();
        t2.start();
    }
}
英文:

I'm trying to get understand Semaphores in Java and I want to use parallel threads to simultaneously generate numbers in an array and perform operations with that data without altering the array itself in order to avoid race conditions. Generating the numbers in the first thread is simple enough and getting the data post generation also wouldn't be too hard if the program worked serially. However, I don't quite understand how to access the array from the other thread while it is being generated. I know that Semaphores are intended to be used to control access to a shared data structure, similar to mutex locks, what's unclear to me is how to declare that (in this case an array) in a legal way.

Here is a basic example:

import java.util.concurrent.Semaphore;
import java.util.Random;
public class Main {
static Semaphore semaphore = new Semaphore(2);
static class Thread1 extends Thread {
private int[] randArray = new int[50];
public void run() {
try {
Random rng = new Random();
semaphore.acquire();
try {
for (int i = 0; i &lt; 50; i++) {
randArray[i] = rng.nextInt() % 100;
System.out.println(&quot;Random number &quot; + i + &quot; : &quot; + randArray[i]);
Thread.sleep(2000);
}
} finally {
semaphore.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Thread2 extends Thread {
public void run() {
try {
semaphore.acquire();
try {
for (int i = 0; i &lt; 50; i++) {
// calculate something using array generated in Thread1
Thread.sleep(2000);
}
} finally {
semaphore.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
t1.start();
Thread2 t2 = new Thread2();
t2.start();
}
}

答案1

得分: 1

创建信号量empty。
启动两个线程。
每当Thread1加载一个数组索引时,发出一个信号量单位。
在Thread 2中,在处理索引之前,在循环中等待信号量。

去掉Sleep调用。

英文:

Create the semaphore empty.
Start both threads.
Every time Thread1 loads an array index, post a semaphore unit.
In Thread 2, wait on the semahore in the loop before processing an index.

Get rid of the Sleep calls.

答案2

得分: -1

首先,这里没有共享数据结构,数组属于Thread-1,仅此而已。

其次,信号量不适合这种用例。如果我理解正确,您希望在元素生成后立即进行逐个处理。信号量可以像您的代码中一样使用,但这将完全依赖于纯粹的运气,即Thread-1总是在完成任务后,Thread-2立即开始执行——在现实生活中不太可能发生。这仅涉及程序的流程,而将内存一致性错误排除在外。虽然可以重写代码,为每个元素使用信号量,但我认为会变得非常混乱。

信号量基本上就像现代COVID-19时代的商店 - 同一时间只能容纳5个人。当有人走进来时,就像是semaphore.acquire(),当有人走出去时 - semaphore.release()。如果有人想进入商店,但空间不足 - 他就等待下一个人离开(semaphore.acquire()会等待直到semaphore.release())。

基本上,您可以使用原子类(例如AtomicInteger)、锁甚至信号量来编写此程序,如果您非常固执,它看起来会运行正常(在大多数情况下确实如此),但它可能会有与Java内存模型相关的微妙错误(Thread-1写入但Thread-2看不到更改),除非您知道自己在做什么。我建议使用java.util.concurrent中的某些结构,比如AtomicIntegerArray。

英文:

Well, first of all you have no shared data structures here, the array belongs to Thread-1 and that's it.

Second - semaphores do not fit well for this use case. If I understood correctly you want 1 by 1 processing as soon as the element is generated. Semaphores could be used like in your code, but you would be relying on pure luck, that Thread-1 always does his thing and Thread-2 starts right after - not gonna happen in real life. And that's just flow of the program, memory consistency errors aside. This could be rewritten to use semaphores for each element, but that's just to much mess in my opinion.

Semaphores are basically like stores in modern COVID-19 times - there can be only 5 people in the store at a time. When a person walks in it's like semaphore.acquire(), and when a person walks out - semaphore.release(). If someone wants to enter and there is not enough space in the store - he waits for the next person to leave (semaphore.acquire() waits until semaphore.release()).

Basically, you could write this program using atomic classes (like AtomicInteger), locks or even semaphores if you were really stubborn, and it would appear to work (and in most cases it would), but it would have subtle errors related to java memory model (Thread-1 writing and Thread-2 not seeing the changes), unless you knew what you are doing. I suggest using some structure from java.util.concurrent - like AtomicIntegerArray.

huangapple
  • 本文由 发表于 2020年8月31日 02:09:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63660591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定