Java volatile数组和多线程排序
我正在考虑使用一个volatile数组实现多线程排序。假设我有一个长度为N和M的数组,它将对数组的子范围进行排序。这些子范围是不相交的。然后,在主线程中,我将合并部分排序的数组 示例代码:Java volatile数组和多线程排序,java,arrays,multithreading,sorting,volatile,Java,Arrays,Multithreading,Sorting,Volatile,我正在考虑使用一个volatile数组实现多线程排序。假设我有一个长度为N和M的数组,它将对数组的子范围进行排序。这些子范围是不相交的。然后,在主线程中,我将合并部分排序的数组 示例代码: final int N = .... volatile MyClass[] array = new MyClass[N]; //... fill array with values void sort(){ MyThread[] workers = new MyThread[M]; int
final int N = ....
volatile MyClass[] array = new MyClass[N];
//... fill array with values
void sort(){
MyThread[] workers = new MyThread[M];
int len = N/M; //length of the sub-range
for(int i=0;i<M;++i){
workers[i] = new MyThread(i*len, (i+1)*len);
workers[i].start();
}
for(int i=0;i<M;++i)workers.join();
//now synchronization in memory using "happens before"
//will it work?
array = array;
//...merge sorted sub-ranges into one sorted array
}
private class MyThread extends Thread{
final int from;
final int to;
public MyThread(int from, int to){ ..... }
public void run(){
//...something like: quicksort(array, from, to);
//...without synchronization, ranges <from, to> are exclusive
}
final int N=。。。。
volatile MyClass[]数组=新的MyClass[N];
//... 用值填充数组
空排序(){
MyThread[]workers=新的MyThread[M];
int len=N/M;//子范围的长度
对于(int i=0;i不是答案,只是一些想法:
没有易失性数组。只有字段可以是易失性的。您已经声明了一个名为“array”的易失性字段,并使用对数组对象的引用对其进行了初始化
看起来您希望语句,array=array
充当一个完整的内存屏障。我不知道它是否会,或者答案是否取决于您使用的编译器、JVM和操作系统。也许有比我更专业的人可以回答
但我不喜欢它有两个原因:一个是,它看起来像一个禁止操作。它是一个邀请,邀请其他一些不理解您试图做什么的程序员来通过删除代码来“清理”代码。像这样一个棘手的语句应该包装在一个函数中,并用一个名称来解释这个技巧
第二,该语句的功能与字段引用的数组无关。最好使用volatile int字段或volatile somethingelse字段,该字段显然与数组没有连接,从而提醒注意,重要的是字段值以外的内容
更新:根据Brian Goetz的说法,这一条语句不能满足您的需要。您需要的是每个工作线程在完成其工作后更新volatile字段,然后您需要主线程在尝试查看工作线程的结果之前读取volatile字段
另一方面,你需要屏障吗?工作线程全部终止,主线程加入它们难道还不够吗?再说一次,也许有比我更专业的人可以回答。你所做的看起来很混乱,正如建议的那样,可能无法按预期工作
如果您使用Java8,那么并行排序可能适合您--
对单个数组进行并行排序是一个恐怖的表演。如果创建一个新的排序元素数组,那么并行排序就相当简单了
创建子数组的对象(最终需要这样做)。将每个对象传递给一个线程。让线程并行排序它们的对象。完成所有排序后,将排序后的对象合并到一个新数组中
这意味着需要更多的内存,但这很容易,您不需要担心易失性或同步问题。N和M将有多大?目标系统可以本地运行多少线程?线程之间上下文切换的开销可能会消耗多线程sorti的大部分加速ng阶段。您将得到大量复杂的代码和(可能)一个小的性能增益。N约为10^6,M是处理器与普通集合协同处理一百万个元素的数量。sort()
在我的机器上,整数平均需要400毫秒,这些整数的十六进制字符串平均需要650毫秒。除非MyClass
有一个超级复杂的比较逻辑,否则您需要几秒钟的时间,就像我为简单起见写的排序一样。工作线程在排序之前还执行其他操作,整个过程在iter中重复(我的代码是遗传算法的一个实现)是的,你是对的,这个表不需要是不稳定的,我想我可以使用易失性的“标志”字段。我不确定这里是否有障碍。请阅读我的编辑。谢谢你的建议,我考虑把我的数组分成子数组。那么,我需要这个易失性的屏障吗?不,你不能同时访问任何字段。谢谢你。化脓。