当前位置: 首页 > 编程笔记 >

java多线程-同步块实例讲解

越嘉茂
2023-03-14
本文向大家介绍java多线程-同步块实例讲解,包括了java多线程-同步块实例讲解的使用技巧和注意事项,需要的朋友参考一下

java多线程-同步块

Java 同步块(synchronized block)用来标记方法或者代码块是同步的。Java 同步块用来避免竞争。本文介绍以下内容:

  1. Java 同步关键字(synchronzied)
  2. 实例方法同步
  3. 静态方法同步
  4. 实例方法中同步块
  5. 静态方法中同步块
  6. Java 同步示例

Java 同步关键字(synchronized)

Java 中的同步块用 synchronized 标记。同步块在 Java 中是同步在某个对象上。所有同步在一个对象上的同步块在同时只能被一个线程进入并执行操作。所有其他等待进入该同步块的线程将被阻塞,直到执行该同步块中的线程退出。

有四种不同的同步块:

  1. 实例方法
  2. 静态方法
  3. 实例方法中的同步块
  4. 静态方法中的同步块

上述同步块都同步在不同对象上。实际需要那种同步块视具体情况而定。

实例方法同步

下面是一个同步的实例方法:

 public synchronized void add(int value){
this.count += value;
 }

静态方法同步

静态方法同步和实例方法同步方法一样,也使用 synchronized 关键字。Java 静态方法同步如下示例:

public static synchronized void add(int value){
 count += value;
 }

同样,这里 synchronized 关键字告诉 Java 这个方法是同步的。

静态方法的同步是指同步在该方法所在的类对象上。因为在 Java 虚拟机中一个类只能对应一个类对象,所以同时只允许一个线程执行同一个类中的静态同步方法。

对于不同类中的静态同步方法,一个线程可以执行每个类中的静态同步方法而无需等待。不管类中的那个静态同步方法被调用,一个类只能由一个线程同时执行。

实例方法中的同步块

有时你不需要同步整个方法,而是同步方法中的一部分。Java 可以对方法的一部分进行同步。

在非同步的 Java 方法中的同步块的例子如下所示:

public void add(int value){

 synchronized(this){
  this.count += value;
 }
 }

示例使用 Java 同步块构造器来标记一块代码是同步的。该代码在执行时和同步方法一样。

注意 Java 同步块构造器用括号将对象括起来。在上例中,使用了“this”,即为调用 add 方法的实例本身。在同步构造器中用括号括起来的对象叫做监视器对象。上述代码使用监视器对象同步,同步实例方法使用调用方法本身的实例作为监视器对象。

一次只有一个线程能够在同步于同一个监视器对象的 Java 方法内执行。

下面两个例子都同步他们所调用的实例对象上,因此他们在同步的执行效果上是等效的。

 public class MyClass {

 public synchronized void log1(String msg1, String msg2){
  log.writeln(msg1);
  log.writeln(msg2);
 }

 public void log2(String msg1, String msg2){
  synchronized(this){
   log.writeln(msg1);
   log.writeln(msg2);
  }
 }
 }

在上例中,每次只有一个线程能够在两个同步块中任意一个方法内执行。

如果第二个同步块不是同步在 this 实例对象上,那么两个方法可以被线程同时执行。

静态方法中的同步块

和上面类似,下面是两个静态方法同步的例子。这些方法同步在该方法所属的类对象上。

public class MyClass {
 public static synchronized void log1(String msg1, String msg2){
  log.writeln(msg1);
  log.writeln(msg2);
 }

 public static void log2(String msg1, String msg2){
  synchronized(MyClass.class){
   log.writeln(msg1);
   log.writeln(msg2);
  }
 }
 }

这两个方法不允许同时被线程访问。

如果第二个同步块不是同步在 MyClass.class 这个对象上。那么这两个方法可以同时被线程访问。

Java 同步实例

在下面例子中,启动了两个线程,都调用 Counter 类同一个实例的 add 方法。因为同步在该方法所属的实例上,所以同时只能有一个线程访问该方法。

public class Counter{
  long count = 0;

  public synchronized void add(long value){
  this.count += value;
  }
 }
 public class CounterThread extends Thread{

  protected Counter counter = null;

  public CounterThread(Counter counter){
  this.counter = counter;
  }

  public void run() {
 for(int i=0; i<10; i++){
   counter.add(i);
  }
  }
 }
 public class Example {

 public static void main(String[] args){
  Counter counter = new Counter();
  Thread threadA = new CounterThread(counter);
  Thread threadB = new CounterThread(counter);

  threadA.start();
  threadB.start();
 }
 }

创建了两个线程。他们的构造器引用同一个 Counter 实例。Counter.add 方法是同步在实例上,是因为 add 方法是实例方法并且被标记上 synchronized 关键字。因此每次只允许一个线程调用该方法。另外一个线程必须要等到第一个线程退出 add()方法时,才能继续执行方法。

如果两个线程引用了两个不同的 Counter 实例,那么他们可以同时调用 add()方法。这些方法调用了不同的对象,因此这些方法也就同步在不同的对象上。这些方法调用将不会被阻塞。如下面这个例子所示:

public class Example {

 public static void main(String[] args){
  Counter counterA = new Counter();
  Counter counterB = new Counter();
  Thread threadA = new CounterThread(counterA);
  Thread threadB = new CounterThread(counterB);

  threadA.start();
  threadB.start();
 }
 }

注意这两个线程,threadA 和 threadB,不再引用同一个 counter 实例。CounterA 和 counterB 的 add 方法同步在他们所属的对象上。调用 counterA 的 add 方法将不会阻塞调用 counterB 的 add 方法。

以上就是对Java 多线程同步块的知识讲解,后续继续补充相关资料,谢谢大家对本站的支持!

 类似资料:
  • 本文向大家介绍Java 多线程实例讲解(一),包括了Java 多线程实例讲解(一)的使用技巧和注意事项,需要的朋友参考一下 Java多线程(一) 多线程作为Java中很重要的一个知识点,在此还是有必要总结一下的。 一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点。掌握了上图中的各知识点,Java中的多线

  • 本文向大家介绍java 多线程-线程通信实例讲解,包括了java 多线程-线程通信实例讲解的使用技巧和注意事项,需要的朋友参考一下 线程通信的目标是使线程间能够互相发送信号。另一方面,线程通信使线程能够等待其他线程的信号。 通过共享对象通信 忙等待 wait(),notify()和 notifyAll() 丢失的信号 假唤醒 多线程等待相同信号 不要对常量字符串或全局对象调用 wait() 通过共

  • 本文向大家介绍JAVA线程同步实例教程,包括了JAVA线程同步实例教程的使用技巧和注意事项,需要的朋友参考一下 线程是Java程序设计里非常重要的概念,本文就以实例形式对此加以详细解读。具体分析如下: 首先,线程加锁有什么用处呢?举个例子:比如你现在有30000块大洋在银行存着,现在你到银行取钱,当你输入密码完成后,已经输入取款金额,比如你输入的是20000,就是在银行给你拿钱这个时刻,你老婆也去

  • 本文向大家介绍Java线程同步实例分析,包括了Java线程同步实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java线程同步的用法。分享给大家供大家参考。具体分析如下: 多线程的使用为我们的程序提供了众多的方便,同时它也给我们带来了以往没有考虑过的麻烦。当我们使用多线程处理共享资源时意外将会发生:比如我们一起外出就餐,每个人都是一个线程,餐桌上的食物则是共享资源,当我看到红烧鸡腿

  • 本文向大家介绍实例讲解php实现多线程,包括了实例讲解php实现多线程的使用技巧和注意事项,需要的朋友参考一下 我们首先来看一个示例 当执行上述操作时,即使在耗时的处理结束之前也显示处理完成。 由于“ > / dev / null& ”返回的值丢失,我们不会等待响应。 因此,处理完成指示比耗时处理更快。 但是,该方法不知道耗时的处理何时结束。 不要忘记考虑采取日志的执行,登录DB等方法向用户传递执

  • 本文向大家介绍java多线程编程之Synchronized块同步方法,包括了java多线程编程之Synchronized块同步方法的使用技巧和注意事项,需要的朋友参考一下 文章分享了4个例子对synchronized的详细解释 1、是否加synchronized关键字的不同 加了synchronized关键字的输出结果如下 会先输出一组0-4,接着再输出下一组,两个线程顺序执行 excute:0