Java线程同步的四种方式详解(建议收藏) mikechen的互联网架构()

  本篇文章为你整理了Java线程同步的四种方式详解(建议收藏) – mikechen的互联网架构()的详细内容,包含有 Java线程同步的四种方式详解(建议收藏) – mikechen的互联网架构,希望能帮助你了解 Java线程同步的四种方式详解(建议收藏) – mikechen的互联网架构。

   Java线程同步的四种方式详解(建议收藏)

  Java线程同步属于Java多线程与并发编程的核心点,需要重点掌握,下面我就来详解Java线程同步的4种主要的实现方式@mikechen

  
 

  什么是线程同步线程同步的几种方式1、使用synchronized关键字2.使用ReentrantLock3.使用原子变量实现线程同步4.ThreadLocal实现线程同步

  什么是线程同步

  当使用多个线程来访问同一个数据时,将会导致数据不准确,相互之间产生冲突,非常容易出现线程安全问题,如下图所示:

  比如多个线程都在操作同一数据,都打算修改商品库存,这样就会导致数据不一致的问题。

  线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。

  所以我们用同步机制来解决这些问题,加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。

  

  线程同步的几种方式

  1、使用synchronized关键字

  这种方式比较灵活,修饰一个代码块,被修饰的代码块称为同步语句块。

  其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象,如下格式:

  

synchronized(对象) { //得到对象的锁,才能操作同步代码

 

   需要被同步代码;

  

 

  通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。

  具体的示例如下:

  

public class SynchronizedThread {

 

   class Bank {

   private int account = 200;

   public int getAccount() {

   return account;

   * 用同步方法实现

   * @param money

   public synchronized void save(int money) {

   account += money;

   * 用同步代码块实现

   * @param money

   public void save1(int money) {

   synchronized (this) {

   account += money;

   class NewThread implements Runnable {

   private Bank bank;

   public NewThread(Bank bank) {

   this.bank = bank;

   @Override

   public void run() {

   for (int i = 0; i i++) {

   // bank.save1(10);

   bank.save(10);

   System.out.println(i + "账户余额为:" + bank.getAccount());

   * 建立线程,调用内部类

   public void useThread() {

   Bank bank = new Bank();

   NewThread new_thread = new NewThread(bank);

   System.out.println("线程1");

   Thread thread1 = new Thread(new_thread);

   thread1.start();

   System.out.println("线程2");

   Thread thread2 = new Thread(new_thread);

   thread2.start();

   public static void main(String[] args) {

   SynchronizedThread st = new SynchronizedThread();

   st.useThread();

  

 

  

  2.使用ReentrantLock

  ReentrantLock类是可重入、互斥、实现了Lock接口的锁,它与使用synchronized方法具有相同的基本行为和语义,并且扩展了其能力。

  

 private int account = 100;

 

   //需要声明这个锁

   private Lock lock = new ReentrantLock();

   public int getAccount() {

   return account;

   //这里不再需要synchronized

   public void save(int money) {

   lock.lock();

   try{

   account += money;

   }finally{

   lock.unlock();

   }

 

  

  synchronized 与 Lock 的对比

  ReentrantLock是显示锁,手动开启和关闭锁,别忘记关闭锁;

  synchronized 是隐式锁,出了作用域自动释放;

  ReentrantLock只有代码块锁,synchronized 有代码块锁和方法锁;

  使用 ReentrantLock锁,JVM 将花费较少的时间来调度线程,线程更好,并且具有更好的扩展性(提供更多的子类);

  优先使用顺序:

  ReentrantLock synchronized 同步代码块 synchronized 同步方法

  

  3.使用原子变量实现线程同步

  为了完成线程同步,我们将使用原子变量(Atomic***开头的)来实现。

  比如典型代表:AtomicInteger类存在于java.util.concurrent.atomic中,该类表示支持原子操作的整数,采用getAndIncrement方法以原子方法将当前的值递加。

  具体示例如下:

  

 private AtomicInteger account = new AtomicInteger(100);

 

   public AtomicInteger getAccount() {

   return account;

   public void save(int money) {

   account.addAndGet(money);

   }

 

  

  4.ThreadLocal实现线程同步

  如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响,从而实现线程同步。

  具体代码示例如下:

  

//只改Bank类,其余代码与上同

 

   public class Bank{

   // 创建一个线程本地变量 ThreadLocal

   private static ThreadLocal Integer account = new ThreadLocal Integer (){

   @Override

   //返回当前线程的"初始值"

   protected Integer initialValue(){

   return 100;

   public void save(int money){

   //设置线程副本中的值

   account.set(account.get()+money);

   public int getAccount(){

   //返回线程副本中的值

   return account.get();

   }

 

  

   以上!

   关注作者「mikechen」的公众号,即送《阿里架构面试资料合集》

  关注公众号回复【架构】,即可获取《阿里架构师进阶从0到1全部合集》,回复【面试】即可获取《1000+大厂面试题及答案》

  以上就是Java线程同步的四种方式详解(建议收藏) – mikechen的互联网架构()的详细内容,想要了解更多 Java线程同步的四种方式详解(建议收藏) – mikechen的互联网架构的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: