java - 显示 Java 中与 2 个线程同步的用法

标签 java multithreading parallel-processing synchronization thread-safety

我一直在寻找多线程教程和那些特定于同步的教程,但我一直无法实现我需要的东西。
它展示了我的程序中发生的同步。
基本上,我有一个类从其他类继承了一些函数,这些函数需要同步,以便两个线程不会同时修改对象(没有数据损坏)。
我之前在没有同步关键字的情况下实现了代码,所以我可以设法看到数据损坏的发生。

 EditOptionsMethods e1;
    int threadNo;

    public EditOptions() {
        e1 = new BuildAuto();
        run();
    }

    public void run() {
        System.out.println("Thread running.");

        switch (threadNo) {
            case 0:

                break;

            case 1:
                break;
        }

    }

    public void setOptions(String optSetName1, String desiredOption1, String optSetName2, String desiredOption2) {
        e1.s_Option(optSetName1, desiredOption1); // 
        e1.s_Option(optSetName2, desiredOption2);
    }
s_Option 必须同步,因此两个线程都不会发生。
我首先将在没有同步的情况下使用它,然后我可以初始化一个循环(具有高索引量,假设为 1000,然后我用第一个线程添加,然后用第二个线程减去)以查看发生的损坏作为示例。
但我没有找到一种方式来展示这一点。
如果有人知道我如何实现这一点,那就太棒了。

最佳答案

首先创建一个结构来保存线程:

   List<Thread> threads = new ArrayList<>();
然后初始化它,并将工作分配给线程:
   int total_threads = 2;
   for(int i = 0; i < total_threads; i++){
       Thread thread  = new Thread(() -> {
           // the work to be done by the threads
       });
       threads.add(thread);
   }
运行线程:
threads.forEach(Thread::start);
最后,等待线程完成它们的工作:
   threads.forEach(t -> {
       try {
                t.join();
       } catch (InterruptedException e) {
                e.printStackTrace();
        }
   });
用一个运行的例子:
import java.util.*;

public class SomeClass {

    private int x;

    public void addX(int y){ x = x + y;}


    public static void main(String[] args) {
           SomeClass example = new SomeClass();
           List<Thread> threads = new ArrayList<>();
           int total_threads = 2;
           for(int i = 1; i < total_threads + 1; i++){
               final int threadID = i;
               Thread thread  = new Thread(() -> {
                   for(int j = 0; j < 1000; j++ )
                    example.addX((threadID % 2 == 0) ? -threadID : threadID);
               });
               threads.add(thread);
           }
           threads.forEach(Thread::start);
           threads.forEach(t -> {
               try {
                        t.join();
               } catch (InterruptedException e) {
                        e.printStackTrace();
                }
           });
           System.out.println(example.x);
    }
}
现在尝试在同步和不同步线程完成的工作的情况下运行上面的示例:
   Thread thread  = new Thread(() -> {
   for(int j = 0; j < 1000; j++ )
       example.addX((threadID % 2 == 0) ? -threadID : threadID);
   });
相对:
 Thread thread  = new Thread(() -> {
 synchronized(example){ // <-- adding synchronization 
    for(int j = 0; j < 1000; j++ )
      example.addX((threadID % 2 == 0) ? -threadID : threadID);
   }
 });
对于使用同步的版本,您可以根据需要多次运行代码,输出将始终为 -1000 (使用 2 个线程)。但是,对于没有同步的版本,由于在更新变量 x 期间发生竞争条件,输出将是不确定的。 .
而不是使用 Thread直接类,你可以选择更高的抽象,即 executors :
public class SomeClass2 {

  private int x;

  public void addX(int y){x = x + y;}

  public static void main(String[] args) {
      SomeClass2 example = new SomeClass2();
      int total_threads = 2;
      ExecutorService pool = Executors.newFixedThreadPool(total_threads);
      pool.execute(() -> {
         synchronized (example) {
            parallel_task(example, -2);
        }
      });
      pool.execute(() -> {
        synchronized (example) {
            parallel_task(example, 1);
         }
      });

      pool.shutdown();
      try { pool.awaitTermination(1, TimeUnit.MINUTES);} 
      catch (InterruptedException e) {e.printStackTrace();}  
      System.out.println(example.x);
}

private static void parallel_task(SomeClass2 example, int i) {
    thread_sleep();
    for (int j = 0; j < 1000; j++)
        example.addX(i);
}

private static void thread_sleep() {
    try { Thread.sleep(1000); } 
    catch (InterruptedException e) {
        e.printStackTrace();
    }
 }
}
我添加了 thread_sleep()确保两个并行任务不会被线程池中的同一个线程占用。

关于java - 显示 Java 中与 2 个线程同步的用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65166368/

相关文章:

haskell - 为什么我们在 Haskell 中需要 'seq' 或 'pseq' 和 'par'?

c++ 如何优雅地将 c++17 并行执行与计算整数的 for 循环一起使用?

java - 我应该使用 java collection sort() 还是实现我自己的?

java - Curator Hierarchy Locking(重叠锁)

java.util.Scanner > useDelimiter() 结合 hasNextInt() before 和 nextInt() after

python - 使用 asyncio 使 websocket 回调异步

java - 核心java多线程-线程没有结束

java - 在固定的时间段内等待多个 ExecutorServices 的终止

c# - C# 中的任务 - 使用 Random 的结果不明确

javascript - Citrix 从 Web 应用程序检索客户端 IP 地址