Java 教程

Java 控制语句

面向对象编程

Java 内置类

Java 文件处理

Java 错误和异常

Java 多线程

Java 同步

Java 网络

Java 集合

Java 接口

Java 数据结构

Java 集合算法

高级 Java

Java 杂项

Java API 和框架

Java 类引用

Java 有用资源

Java - 块同步



当我们在 Java 程序中启动 两个或多个线程 时,可能会出现多个线程尝试访问相同资源的情况,最终由于并发问题而产生不可预见的结果。例如,如果多个线程尝试写入同一个文件,则它们可能会损坏数据,因为其中一个线程可能会覆盖数据,或者当一个线程正在打开同一个文件时,另一个线程可能正在关闭同一个文件。

因此,需要同步多个线程的操作,并确保在给定时间点只有一个线程可以访问资源。这是使用称为监视器的概念实现的。Java 中的每个对象都与一个监视器关联,线程可以锁定或解锁该监视器。一次只有一个线程可以持有监视器的锁。

Java 中的块同步

Java 编程语言提供了一种非常方便的方法来创建线程并使用同步块 同步 它们的作业。您将共享资源保留在此块中。

语法

以下是 synchronized 语句的一般形式:

synchronized(objectidentifier) {
   // Access shared variables and other shared resources
}

这里,objectidentifier 是对一个对象的引用,其锁与 synchronized 语句表示的监视器关联。现在我们将看两个示例,我们将在其中使用两个不同的线程打印计数器。当线程不同步时,它们打印的计数器值不是按顺序的,但是当我们将计数器放在 synchronized() 块内打印时,它会为两个线程按顺序打印计数器。

无同步的多线程示例

这是一个简单的示例,它可能打印或不打印按顺序的计数器值,并且每次我们运行它时,它都会根据 CPU 对线程的可用性产生不同的结果。

示例

package com.tutorialspoint;

class PrintDemo {
   public void printCount() {
      try {
         for(int i = 5; i >  0; i--) {
            Thread.sleep(50);
            System.out.println("Counter   ---   "  + i );
         }
      } catch (Exception e) {
         System.out.println("Thread  interrupted.");
      }
   }
}

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   PrintDemo  printDemo;

   ThreadDemo( String name,  PrintDemo pd) {
      threadName = name;
      printDemo = pd;
   }
   
   public void run() {
      printDemo.printCount();
      System.out.println("Thread " +  threadName + " exiting.");
   }

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

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

      PrintDemo printDemo = new PrintDemo();

      ThreadDemo t1 = new ThreadDemo( "Thread - 1 ", printDemo );
      ThreadDemo t2 = new ThreadDemo( "Thread - 2 ", printDemo );

      t1.start();
      t2.start();

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

输出

每次运行此程序都会产生不同的结果:

Starting Thread - 1 
Starting Thread - 2 
Counter   ---   5
Counter   ---   5
Counter   ---   4
Counter   ---   4
Counter   ---   3
Counter   ---   3
Counter   ---   2
Counter   ---   2
Counter   ---   1
Counter   ---   1
Thread Thread - 1  exiting.
Thread Thread - 2  exiting.

块级同步的多线程示例

这是同一个示例,它按顺序打印计数器值,并且每次我们运行它时,它都会产生相同的结果。我们在块上放置了 synchronized 关键字,以便计数器增量代码现在在方法执行期间根据对象被锁定。我们使用当前对象作为锁,将其作为参数传递给 synchronized 块。

示例

package com.tutorialspoint;

class PrintDemo {
   public void printCount() {
      try {
         for(int i = 5; i > 0; i--) {
            Thread.sleep(50);
            System.out.println("Counter   ---   "  + i );
         }
      } catch (Exception e) {
         System.out.println("Thread  interrupted.");
      }
   }
}

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   PrintDemo printDemo;

   ThreadDemo( String name, PrintDemo pd) {
      threadName = name;
      printDemo = pd;
   }
   
   public void run() {
      synchronized(printDemo) {
         printDemo.printCount();
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }

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

public class TestThread {

   public static void main(String args[]) {
      PrintDemo printDemo = new PrintDemo();

      ThreadDemo t1 = new ThreadDemo( "Thread - 1 ", printDemo );
      ThreadDemo t2 = new ThreadDemo( "Thread - 2 ", printDemo );

      t1.start();
      t2.start();

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

输出

每次运行此程序都会产生相同的结果:

Starting Thread - 1 
Starting Thread - 2 
Counter   ---   5
Counter   ---   4
Counter   ---   3
Counter   ---   2
Counter   ---   1
Thread Thread - 1  exiting.
Counter   ---   5
Counter   ---   4
Counter   ---   3
Counter   ---   2
Counter   ---   1
Thread Thread - 2  exiting.

方法级同步的多线程示例

这是同一个示例,它按顺序打印计数器值,并且每次我们运行它时,它都会产生相同的结果。这次我们在方法上放置了 synchronized 关键字,以便整个方法在方法执行期间根据对象被锁定。

示例

package com.tutorialspoint;

class PrintDemo extends Thread {
   public void printCount() {
      try {
         for(int i = 5; i > 0; i--) {
            Thread.sleep(50);
            System.out.println("Counter --- " + i );
         }
      } catch (Exception e) {
         System.out.println("Thread " + Thread.currentThread().getName()+" interrupted.");
      }
   }
   public synchronized void run() {
      printCount();
      System.out.println("Thread " + Thread.currentThread().getName() + " exiting.");
   }
}
public class TestThread {
   public static void main(String args[]) {
      PrintDemo printDemo = new PrintDemo();
      Thread t1 = new Thread(printDemo );
      Thread t2 = new Thread(printDemo );
      t1.start();
      t2.start();
      // wait for threads to end
      try {
         t1.join();
         t2.join();
      } catch ( Exception e) {
         System.out.println("Interrupted");
      }
   }
}

输出

每次运行此程序都会产生相同的结果:

Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread-1 exiting.
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread-2 exiting.
广告