简体   繁体   English

显示在 Java 中使用 2 线程同步的用法

[英]Showing usage of Synchronization with 2 Threads in Java

I've been looking about multi threading tutorials and those specific about synchronization, but I haven't been able to implement something that I need.我一直在寻找多线程教程和特定于同步的教程,但我无法实现我需要的东西。

It's a showcase of a synchronization happening in my program.这是我的程序中发生的同步的展示。

Basically, I have one class that inherits some functions from other class, those functions needs to be synchronized in order for both of threads doesn't modify an object at the same time (no data corruption).基本上,我有一个 class 继承了其他 class 的一些功能,这些功能需要同步,以便两个线程不会同时修改 object(无数据损坏)。

I previously implemented the code without the synchronize keyword, so I could manage to see the data corruption occurring.我之前在没有 synchronize 关键字的情况下实现了代码,因此我可以设法看到发生的数据损坏。

 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 will have to be synchronized so both threads won't occur. s_Option 必须同步,这样两个线程都不会发生。 I firstly will have it without synchronize, then I can initialize a loop (with high index amount, lets say 1000 and then I add with first thread, and subtract with second thread) to see the corruption occurring as an example.我首先将它没有同步,然后我可以初始化一个循环(具有高索引量,假设为 1000,然后我用第一个线程添加,并用第二个线程减去)以查看发生的损坏作为示例。

But I don't find a way of showing this.但我找不到展示这一点的方法。

If someone has an idea of how I could possibly implement this, that'd be awesome.如果有人知道我如何实现这一点,那就太棒了。

First create a structure that will hold the threads:首先创建一个包含线程的结构:

   List<Thread> threads = new ArrayList<>();

then initialize it, and assign work to the threads:然后初始化它,并将工作分配给线程:

   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);
   }

Run the threads:运行线程:

threads.forEach(Thread::start);

Finally, wait for the threads to finish their work:最后,等待线程完成它们的工作:

   threads.forEach(t -> {
       try {
                t.join();
       } catch (InterruptedException e) {
                e.printStackTrace();
        }
   });

With a running example:通过一个运行示例:

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);
    }
}

Now try to run the example above with and without synchronizing the work done by the threads:现在尝试在同步和不同步线程完成的工作的情况下运行上面的示例:

   Thread thread  = new Thread(() -> {
   for(int j = 0; j < 1000; j++ )
       example.addX((threadID % 2 == 0) ? -threadID : threadID);
   });

versus:相对:

 Thread thread  = new Thread(() -> {
 synchronized(example){ // <-- adding synchronization 
    for(int j = 0; j < 1000; j++ )
      example.addX((threadID % 2 == 0) ? -threadID : threadID);
   }
 });

With the version that uses synchronization, you can run the code as many times as you want the output will always be -1000 (using 2 threads).使用使用同步的版本,您可以根据需要多次运行代码 output 将始终为-1000 (使用 2 个线程)。 However, with the version without the synchronization the output will be non-deterministic due to the race condition happening during the updates of the variable x .但是,对于没有同步的版本,output 将是不确定的,因为在变量x更新期间发生竞争条件。

Instead of using the Thread class directly, you can opt for a higher abstraction, namely executors :除了直接使用Thread class 之外,您还可以选择更高的抽象,即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();
    }
 }
}

I have added the thread_sleep() to ensure that both parallel tasks are not pick up by the same thread from the thread pool.我添加了thread_sleep()以确保两个并行任务不会被线程池中的同一线程拾取。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM