详谈Java多线程的几个常用关键字

 更新时间:2017年04月27日 09:03:23   投稿:jingxian  
下面小编就为大家带来一篇详谈Java多线程的几个常用关键字。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

一、同步(synchronized)和异步(asynchronized)

1、同步(synchronized)简单说可以理解为共享的意思,如果资源不是共享的,就没必要进行同步。设置共享资源为同步的话,可以避免一些脏读情况。

2、异步(asynchronized)简单说可以理解为独立不受到其他任何制约。

举个例子:

线程1调用了带有synchronized关键字的方法methodA,线程2调用了异步方法methodB,出现的现象是同时控制台输出 t1,t2。

package com.ietree.multithread.sync;

/**
 * 多线程之对象同步锁和异步锁Demo
 *
 * @author ietree
 */
public class SynAndAsynDemo {

  public static void main(String[] args) {
    
    final SynAndAsynDemo mo = new SynAndAsynDemo();
    
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodA();
      }
    },"t1");
    
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodB();
      }
    },"t2");
    
    t1.start();
    t2.start();
  }
  
  // 方法A
  public synchronized void methodA(){
    try {
      System.out.println(Thread.currentThread().getName());
      // 休眠4秒
      Thread.sleep(4000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  
  // 方法B
  public void methodB(){
    System.out.println(Thread.currentThread().getName());
  }
  
}

线程1调用了带有synchronized关键字的方法methodA,线程2调用了带有synchronized关键字的方法methodB,出现的现象是首先输出t1,等待4秒之后再输出t2。

package com.ietree.multithread.sync;

/**
 * 多线程之对象同步锁和异步锁Demo
 *
 * @author ietree
 */
public class SynAndAsynDemo {

  public static void main(String[] args) {
    
    final SynAndAsynDemo mo = new SynAndAsynDemo();
    
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodA();
      }
    },"t1");
    
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodB();
      }
    },"t2");
    
    t1.start();
    t2.start();
  }
  
  // 方法A
  public synchronized void methodA(){
    try {
      System.out.println(Thread.currentThread().getName());
      // 休眠4秒
      Thread.sleep(4000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  
  // 方法B
  public synchronized void methodB(){
    System.out.println(Thread.currentThread().getName());
  }
  
}

结论:

在第一段代码中t1线程先持有object对象的Lock锁,t2线程可以以异步的方式调用对象中的非synchronized修饰的方法,所以同时输出;

在第二段代码中t1线程先持有object对象的Lock锁,t2线程如果在这个时候调用对象中的同步(synchronized)方法则需等待,也就是同步。

二、volatile

作用:volatile关键字的作用是:使变量在多个线程间可见(具有可见性),但是仅靠volatile是不能保证线程的安全性,volatile关键字不具备synchronized关键字的原子性。

Demo1:

package com.ietree.multithread.sync;

public class RunThread extends Thread {
  // volatile
  private boolean isRunning = true;

  private void setRunning(boolean isRunning) {
    this.isRunning = isRunning;
  }

  public void run() {
    System.out.println("进入run方法..");
    int i = 0;
    while (isRunning == true) {
      // ..
    }
    System.out.println("线程停止");
  }

  public static void main(String[] args) throws InterruptedException {
    RunThread rt = new RunThread();
    rt.start();
    Thread.sleep(1000);
    rt.setRunning(false);
    System.out.println("isRunning的值已经被设置了false");
  }
}

程序输出:

进入run方法..
isRunning的值已经被设置了false

之后进入死循环

Demo2:

package com.ietree.multithread.sync;

public class RunThread extends Thread {
  // volatile
  private volatile boolean isRunning = true;

  private void setRunning(boolean isRunning) {
    this.isRunning = isRunning;
  }

  public void run() {
    System.out.println("进入run方法..");
    int i = 0;
    while (isRunning == true) {
      // ..
    }
    System.out.println("线程停止");
  }

  public static void main(String[] args) throws InterruptedException {
    RunThread rt = new RunThread();
    rt.start();
    Thread.sleep(1000);
    rt.setRunning(false);
    System.out.println("isRunning的值已经被设置了false");
  }
}

程序输出:

isRunning的值已经被设置了false
线程停止

总结:当多个线程之间需要根据某个条件确定 哪个线程可以执行时,要确保这个条件在 线程之间是可见的。因此,可以用volatile修饰。

volatile 与 synchronized 的比较:

①volatile轻量级,只能修饰变量。synchronized重量级,还可修饰方法

②volatile只能保证数据的可见性,不能用来同步,因为多个线程并发访问volatile修饰的变量不会阻塞。

synchronized不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized锁对象时,会出现阻塞。

线程安全性包括两个方面,①可见性。②原子性。

从上面自增的例子中可以看出:仅仅使用volatile并不能保证线程安全性。而synchronized则可实现线程的安全性。

以上这篇详谈Java多线程的几个常用关键字就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java Spring MVC4环境搭建实例详解(步骤)

    java Spring MVC4环境搭建实例详解(步骤)

    spring WEB MVC框架提供了一个MVC(model-view-controller)模型-视图-控制器的结构和组件,利用它可以开发更灵活、松耦合的web应用。MVC模式使得整个服务应用的各部分(控制逻辑、业务逻辑、UI界面展示)分离开来,使它们之间的耦合性更低
    2017-08-08
  • 阿里云发布 Spring Boot 新脚手架工程

    阿里云发布 Spring Boot 新脚手架工程

    这篇文章主要介绍了阿里云发布 Spring Boot 新脚手架的相关资料,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,可以参考下
    2020-04-04
  • SpringMVC @RequestMapping注解属性详细介绍

    SpringMVC @RequestMapping注解属性详细介绍

    通过@RequestMapping注解可以定义不同的处理器映射规则,下面这篇文章主要给大家介绍了关于SpringMVC中@RequestMapping注解用法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • SpringBoot3.x中spring.factories SPI 服务发现机制的改变问题小结

    SpringBoot3.x中spring.factories SPI 服务发现机制的改变问题小结

    spring.factories其实是SpringBoot提供的SPI机制,底层实现是基于SpringFactoriesLoader检索ClassLoader中所有jar引入的META-INF/spring.factories文件,这篇文章主要介绍了SpringBoot3.x中spring.factories SPI 服务发现机制的改变,需要的朋友可以参考下
    2023-05-05
  • java volatile关键字作用及使用场景详解

    java volatile关键字作用及使用场景详解

    在本文里我们给大家分享的是关于java volatile关键字作用及使用场景的相关知识点内容,需要的朋友们学习下。
    2019-08-08
  • SpringBoot使用mybatis步骤总结

    SpringBoot使用mybatis步骤总结

    今天给大家带来的是关于Java的相关知识,文章围绕着SpringBoot使用mybatis步骤展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • 修改jvm-sandbox源码导致线程安全分析

    修改jvm-sandbox源码导致线程安全分析

    这篇文章主要为大家介绍了修改jvm-sandbox源码导致线程安全分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • Struts2中ognl遍历数组,list和map方法详解

    Struts2中ognl遍历数组,list和map方法详解

    这篇文章主要介绍了Struts2中ognl遍历数组,list和map方法详解,需要的朋友可以参考下。
    2017-09-09
  • SpringBoot使用Prometheus采集自定义指标数据的方法详解

    SpringBoot使用Prometheus采集自定义指标数据的方法详解

    随着微服务在生产环境大规模部署和应用,随之而来也带来了新的问题,其中比较关键的就是关于微服务的运维和监控,本文将结合微服务运维监控中的指标监控进行详细的说明,需要的朋友可以参考下
    2024-07-07
  • 大话Java混合运算规则

    大话Java混合运算规则

    这篇文章主要介绍了大话Java混合运算规则,小编觉得挺不错的,在这里分享给大家,需要的朋友可以了解下。
    2017-10-10

最新评论