的静态变量的使用,同时使用叉加入
问题陈述: - //这是一个示例,实际阵列尺寸很大的静态变量的使用,同时使用叉加入
假设有A级
public class A{
public static int aa[]=new int[5];
public computeaa(){
for(int i=0;i<5;i++)
aa[i] = useaa(i);
}
//this below function can compute aa[i] value
public int useaa(int i){
if(i<=0)
return 1;
if(aa[i]!=0)
return aa[i];
else
return useaa[i-1]+useaa[i-2];
}
}
而且RecursiveAction B类
@Override
protected void compute() {
// TODO Auto-generated method stub
A z=new A();
A.computeaa();
}
public static void main(String[] args) {
List<B> tasks =new ArrayList<B>();
for(int i=1; i<=2; i++){
//There is 2 fork will created
B =new B();
tasks.add(B);
B.fork();
}
if (tasks.size() > 0) {
for (B task : tasks) {
task.join();
}
}
}
怀疑?
假设叉1计算静态变量AA [2],并且假设当叉2将计算AA [2],可以在此叉2得到的值AA [2],其通过与fork1或计算它会单独计算?
据我了解,fork 2在某些情况下很容易访问fork1的aa,假设fork 2想要计算aa [3],它可以得到已经由fork 1计算出来的值。但是问题是假设fork 1将尝试计算aa [4],计算aa [4],它需要aa [3],已经计算出叉1,但如果fork 1试图获得aa [3],它可能会有可能,但偶然它会得到访问权叉1的aa [3],这是不计算...再次造成一团糟。
我很谜题叉联接好心帮
有简单的问题,我想计算一些阵列所使用的同一个班级,但是在建立一个以上的对象我想使用相同的数组,这是由其他对象计算,以便减少我的计算时间。
如何复制或获取该数组到另一个对象,以便该对象不需要计算?
- 假设叉1计算静态变量AA [2],并且假设当叉2将计算AA [2],可以在此叉2得到的值AA [2] ,其通过与fork1计算或它会分开计算?
假设在不同线程中运行两个B
任务 - 在其上选择不行使任何控制 - 这些两个线程都访问同一阵列对象的相同元件而没有任何同步。任何一个线程都可以读取另一个写入的值。而且,如果他们再次访问该数组元素,他们可能会读取不同的值。该程序没有正确同步,因此不能保证顺序一致性。
开始=“2”>
- 通过我的理解叉2在某些情况下很容易地访问与fork1的AA,假设叉2想计算AA [3],它可以得到其中 已经由计算的值fork 1.但是问题是假设fork 1 将尝试计算aa [4],计算aa [4]时,它需要aa [3],其中fork 1已经计算出来了,但如果fork 1试图得到 aa [3],但偶然它得到aa [3]叉1的访问,这是 不计算...再次造成一团糟。
是的,你的判断是正确的 - 关于可能的行为和关于它是一团糟。
有简单的问题,我想计算一些阵列所使用的 同一个班级,但是在建立一个以上的对象我想用它被其他物体计算的 同一阵列,这样我的计算 时间减少。我如何复制或获取该数组到另一个对象,所以 ,这个对象不需要计算?
在某些情况下,您可能会有不同的线程并行计算数组的不相交部分。然而,由于数据之间的依赖关系,问题中提出的计算不适用于此。因为在计算前2之前没有可以计算过去索引1的元素,所以元素的计算需要以某种方式进行序列化。你不能通过将单个线程用于工作来实现这一点。
完成此类计算后,您可以在线程之间共享已初始化的数组,只要它们以某种方式与计算完成同步。如果任何线程在初始计算完成后修改了阵列,则会应用其他同步要求。
您的具体情况有点棘手,因为很少有具有同步意义的动作存在。特别是,你的数组元素不是(也不可能是)final
,你不能确信你的任务运行的线程只在你使用fork()
;如果你有后者,那么主线程之前做的所有事情都会自动与任务的工作同步。正因为如此,你可能会做这样的事情:
public class A {
// not static:
public int aa[] = new int[5];
public void computeAa() {
aa[0] = 1;
aa[1] = 1;
for (int i = 2; i < aa.length; i++) {
aa[i] = aa[i - 1] + aa[i - 2];
}
}
public int getAa(int i) {
return (i < 0) ? 1 : aa[i];
}
}
public class B extends RecursiveAction {
private A myA;
public RecursiveAction(A a) {
myA = a;
}
@Override
protected void compute() {
synchronized (myA) {
// ensure that myA's initialization is complete
while (myA.aa[0] == 0) {
// not yet initialized
myA.wait();
}
}
// ... do something with myA (without modifying it) ...
}
public static void main(String[] args) {
A theA = new A();
synchronized(theA) {
// synchronize the initialization of theA, because other threads will
// check it
theA.computeAa();
// wake up any threads waiting on the initialization
theA.notifyAll();
}
List<B> tasks = new ArrayList<B>();
for(int i = 1; i <= 2; i++){
//There is 2 fork will created
B = new B(theA);
tasks.add(B);
B.fork();
}
for (B task : tasks) {
task.join();
}
}
}
注意这里说的主线程创建的A
实例和分叉任何任务之前对其进行初始化。它为每个B
提供这个实例(因此它们共享它)。
computeAa中是否需要在main方法中同步,因为其他线程只会在for循环中的程序计数器时才会播放? –
答案看起来很完美,你能否清楚我的疑问。 –
@MukeshGupta,考虑到所涉及的类只有可用的API文档没有理由假设可以安全地省略'synchronized'块,'wait()'或者'notifyAll()'中的任何一个。特别是,主线程中'fork()'调用的相对时间是不够的,因为不同的线程可以看到线程间的动作,例如以不同顺序修改共享变量。两个同步块一起,以及'wait()'和'notifyAll()'的特殊用法确保了适当的全局线程化操作顺序。 –
如何使用['AtomicIntegerArray'](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicIntegerArray.html)? –
提示:当您花时间为我们创建[mcve]时:请遵循遵循Java命名约定的正确有意义的名称。其他任何东西都会显着降低您为我们组合的源代码的价值。含义 - 单独使用a和aa和useaa会使您的代码几乎无法理解。 – GhostCat
除此之外:没有人告诉过你,使用静态在oop中通常是不好的做法吗? – GhostCat