# Java 线程同步

> 原文： [https://javatutorial.net/java-thread-synchronization](https://javatutorial.net/java-thread-synchronization)

本文讨论了 Java 中线程同步的重要性以及如何在程序中实现线程同步。

当您的程序有多个线程时，当不同的线程尝试访问相同的资源或同时执行相同的操作时，可能会出现问题。 这种情况会导致错误和并发问题。 让我们以一个示例为例，您的程序中有两个线程试图读取/写入文本文件。 当两个线程都在写入文件时，一个线程的数据可能会被另一个线程覆盖，并且在读取文件时会发现相同的问题。

因此，线程同​​步是必需的，以便多个线程在任何给定时间点一次访问一个线程。

为什么要使用线程同步？

*   防止线程干扰
*   避免一致性问题和并发问题
*   防止数据丢失

线程同步有互斥和线程间通信两种类型。

*   互斥
*   同步方法。
*   同步块。
*   静态同步。
*   合作（Java 中的线程间通信）

## 同步块

同步块用于线程同步。

`synchronized`关键字用于标识 Java 中的同步块，并基于某些对象进行同步。 其背后的主要概念是，在同一对象上同步的所有同步块一次只能在其中一个线程内执行，这会阻止多个线程同时运行和执行。 尝试进入同步块的所有其他线程将被阻止，直到同步块内的线程退出该块为止。

共享资源保留在此同步块内，以便在给定时间点只有一个线程可以访问特定资源。

同步块的语法如下所示：

```java
synchronized(referencetoobject) {
   // Shared variables and other shared resources are placed here
}

```

## 监视器

在尝试理解和实现 Java 同步时，监视器的概念很重要。

*   Java 中的每个对象都与一个监视器关联
*   线程可以锁定或解锁监视器
*   在给定时间，只有一个线程可以拥有监视器。
*   一次只能有一个线程可以锁定监视器

## 线程同步示例

```java
//We write a program with a simple counter execution.
class Countings {
   public void printing() {
      try {
         for(int i = 5; i > 0; i--) {
            System.out.println( i );
         }
      } catch (Exception e) {
         System.out.println("Thread  interrupted.");
      }
   }
}

class Threadings extends Thread {
   private Thread thrd;
   private String thrdName;
   Countings gg;

   Threadings( String name,  Countings abc) {
      thrdName = name;
      gg = abc;
   }
    public void run() {
      gg.printing();
      System.out.println("Thread " +  thrdName + " exiting.");
   }

   public void start () {
      System.out.println("Starting " +  thrdName );
      if (thrd == null) {
         thrd = new Thread (this, thrdName);
         thrd.start ();
      }
   }
}

public class Tests {
   public static void main(String args[]) {

      Countings gg = new Countings();

      Countings T1 = new Countings ( "Thread - 1 ", gg );
      Countings T2 = new Countings ( "Thread - 2 ", gg );

      T1.start();
      T2.start();

      // threads take some time to end
         try {
         T1.join();
         T2.join();
      } catch ( Exception e) {
         System.out.println("Interrupted");
      }
   }
}

```

输出：（每次运行都会产生不同的结果）

```java
Starting Thread - 1
Starting Thread - 2
5
4
3
5
2
1
4
Thread Thread - 1  exiting.
3
2
1
Thread Thread - 2  exiting.
```

相同的示例，但是这次具有线程同步：

```java
class Countings {
   public void printings() {
      try {
         for(int i = 5; i > 0; i--) {
            System.out.println( i );
         }
      } catch (Exception e) {
         System.out.println("Thread  interrupted.");
      }
   }
}
class Threadings extends Thread {
   private Thread t;
   private String thrdName;
   Countings  gg;

   Threadings( String name,  Countings abc) {
      thrdName = name;
      gg = abc;
   }

   public void run() {
      synchronized(gg) {
         gg.printings();
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }

   public void start () {
      System.out.println("Starting " +  thrdName );
      if (thrd == null) {
         thrd = new Thread (this, thrdName);
         thrd.start ();
      }
   }
}

public class Testings{

   public static void main(String args[]) {
      Countings gg = new Countings();

      Threadings T1 = new Threadings ( "Thread - 1 ", gg );
      Threadings T2 = new Threadings ( "Thread - 2 ", gg );

      T1.start();
      T2.start();

      // wait for threads to end
      try {
         T1.join();
         T2.join();
      } catch ( Exception e) {
         System.out.println("Interrupted");
      }
   }
}

```

输出：（我们看到的输出是同步的，并且每次执行程序都是相同的）

```java
Starting Thread - 1
Starting Thread - 2
5
4
3
2
1
Thread Thread - 1  exiting.
5
4
3
2
1
Thread Thread - 2  exiting.
```