详谈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多线程的几个常用关键字就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 简单谈谈RxJava和多线程并发

    前言 相信对于RxJava,大家应该都很熟悉,他最核心的两个字就是异步,诚然,它对异步的处理非常的出色,但是异步绝对不等于并发,更不等于线程安全,如果把这几个概念搞混了,错误的使用RxJava,是会来带非常多的问题的. RxJava与并发 首先让我们来看一段RxJava协议的原文: Observables must issue notifications to observers serially (not in parallel). They may issue these notificat

  • Java多线程编程小实例模拟停车场系统

    下面分享的是一个Java多线程模拟停车场系统的小实例(Java的应用还是很广泛的,哈哈),具体代码如下: Park类 public class Park { boolean []park=new boolean[3]; public boolean equals() { return true; } } Car: public class Car { private String number; private int position=0; public Car(String number)

  • Java实现多线程文件下载的代码示例

    Java实现多线程文件下载思路: 1.基本思路是将文件分段切割.分段传输.分段保存. 2.分段切割用到HttpUrlConnection对象的setRequestProperty("Range", "bytes=" + start + "-" + end)方法. 3.分段传输用到HttpUrlConnection对象的getInputStream()方法. 4.分段保存用到RandomAccessFile的seek(int start)方法. 5

  • JAVA 多线程爬虫实例详解

    JAVA 多线程爬虫实例详解 前言 以前喜欢Python的爬虫是出于他的简洁,但到了后期需要更快,更大规模的爬虫的时候,我才渐渐意识到Java的强大.Java有一个很好的机制,就是多线程.而且Java的代码效率执行起来要比python快很多.这份博客主要用于记录我对多线程爬虫的实践理解. 线程 线程是指一个任务从头至尾的执行流.线程提供了运行一个任务的机制.对于Java而言,可以在一个程序中并发地启动多个线程.这些线程可以在多处理器系统上同时运行. runnable接口 任务类必须实现runna

  • java实现多线程之定时器任务

    在Java中Timer是java.util包中的一个工具类,提供了定时器的功能.我们可以创建一个Timer对象,然后调用其schedule方法在某个特定的时间去执行一个特定的任务.并且你可以让其以特定频率一直执行某个任务,这个任务是用TimerTask来描述的,我们只需要将要进行的操作写在TimerTask类的run方法中即可.先附上两个小例子一遍让读者了解什么是定时器.接着再分析其中的一些源码实现. 第一个小例子: package com.zkn.newlearn.thread; import

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

    一.同步(synchronized)和异步(asynchronized) 1.同步(synchronized)简单说可以理解为共享的意思,如果资源不是共享的,就没必要进行同步.设置共享资源为同步的话,可以避免一些脏读情况. 2.异步(asynchronized)简单说可以理解为独立不受到其他任何制约. 举个例子: 线程1调用了带有synchronized关键字的方法methodA,线程2调用了异步方法methodB,出现的现象是同时控制台输出 t1,t2. package com.ietree.

  • java多线程编程之使用Synchronized关键字同步类方法

    复制代码 代码如下: public synchronized void run(){     } 从上面的代码可以看出,只要在void和public之间加上synchronized关键字,就可以使run方法同步,也就是说,对于同一个Java类的对象实例,run方法同时只能被一个线程调用,并当前的run执行完后,才能被其他的线程调用.即使当前线程执行到了run方法中的yield方法,也只是暂停了一下.由于其他线程无法执行run方法,因此,最终还是会由当前的线程来继续执行.先看看下面的代码:sych

  • Java多线程并发编程 Volatile关键字

    volatile 关键字是一个神秘的关键字,也许在 J2EE 上的 JAVA 程序员会了解多一点,但在 Android 上的 JAVA 程序员大多不了解这个关键字.只要稍了解不当就好容易导致一些并发上的错误发生,例如好多人把 volatile 理解成变量的锁.(并不是) volatile 的特性: 具备可见性 保证不同线程对被 volatile 修饰的变量的可见性. 有一被 volatile 修饰的变量 i,在一个线程中修改了此变量 i,对于其他线程来说 i 的修改是立即可见的. 如: vola

  • java多线程编程之Synchronized关键字详解

    本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章  一.分析 synchronized可以修饰实例方法,如下形式: public class MyObject { synchronized public void methodA() { //do something.... } 这里,synchronized 关键字锁住的是当前对象.这也是称为对象锁的原因. 为啥锁住当

  • java多线程编程之慎重使用volatile关键字

    volatile关键字相信了解Java多线程的读者都很清楚它的作用.volatile关键字用于声明简单类型变量,如int.float.boolean等数据类型.如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的.但这有一定的限制.例如,下面的例子中的n就不是原子级别的: 复制代码 代码如下: package mythread; public class JoinThread extends Thread{public static volatile int n = 0;p

  • java多线程关键字final和static详解

    这篇文章主要介绍了java多线程关键字final和static详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 final关键字 1.final关键字在单线程中的特点: 1)final修饰的静态成员:必须在进行显示初始化或静态代码块赋值,并且仅能赋值一次. 2)final修饰的类成员变量,可以在三个地方进行赋值:显示初始化.构造代码块和构造方法,并且仅能赋值一次. 3)final修饰的局部变量,必须在使用之前进行显示初始化(并不一定要在定义是

  • Java多线程的常用创建方式总结

    Java现在有四种创建的方式:继承Threa类.实现Runnable接口.实现Callable接口.线程池 Thread.Runnable都在java.lang包下:Callable.线程池都在java.util.concurrent包下 1.继承Thread类,重写run方法 创建一个类继承Thread类,并重写run():因为run()是线程具体执行的方法 在测试类或者main()创建Thread对象,并调用start()启动线程 备注:start()是启动线程,run()是线程执行的业务方

  • java多线程JUC常用辅助类详解

    1.countDownLatch 减法计数器:实现调用几次线程后,在触发另一个任务 简单代码实现: 举例说明:就像五个人在同一房间里,有一个看门的大爷,当五个人都出去后,他才能锁门,也就是说 执行5次出门这个动作的线程后,才出发了锁门的这个动作 import java.util.concurrent.CountDownLatch; /** * @program: juc * @description * @author: 不会编程的派大星 * @create: 2021-04-24 16:55

  • Java多线程并发synchronized 关键字

    目录 基础 修饰普通方法 修饰静态方法 Synchronized 加锁原理 monitorenter monitorexit synchronized 修饰静态方法 优点.缺点及优化 其他说明 基础 Java 在虚拟机层面提供了 synchronized 关键字供开发者快速实现互斥同步的重量级锁来保障线程安全. synchronized 关键字可用于两种场景: 修饰方法. 持有一个对象,并执行一个代码块. 而根据加锁的对象不同,又分为两种情况: 对象锁 类对象锁 以下代码示例是 synchron

  • 详谈java线程与线程、进程与进程间通信

    线程与线程间通信 一.基本概念以及线程与进程之间的区别联系: 关于进程和线程,首先从定义上理解就有所不同 1.进程是什么? 是具有一定独立功能的程序.它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独 立运行的一段程序. 2.线程又是什么? 线程进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源. 在运行时,只是暂用一些计数器.寄存器和栈 . 他们之间的关系 1.一个线程只能属于一个进程,而一个

随机推荐