如何实现Java线程安全问题

这篇文章主要介绍了如何实现Java线程安全问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

解决线程安全问题的第一种方案:使用同步代码块

格式:

  synchronized(锁对象) {

    可能会出现线程安全问题的代码(访问了共享数据的代码)

  }

注意:代码块中的锁对象,可以是任意对象,但必须保证多个线程之间使用的是同一个

锁对象的作用是把同步代码块锁住,同一时间只能让一个线程在同步代码块中执行

package com.fgy.demo02;

/**
 * 实现卖票案例
 */
public class RunnableImpl implements Runnable {
  private int ticket = 100;
  Object obj = new Object();

  @Override
  public void run() {
    while (true) {
      synchronized (obj) {
        if (ticket > 0) {
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
          ticket--;
        }
      }
    }
  }
}
package com.fgy.demo02;

public class Demo01Ticket {
  public static void main(String[] args) {
    RunnableImpl run = new RunnableImpl();
    new Thread(run).start();
    new Thread(run).start();
    new Thread(run).start();
  }
}

解决线程安全问题的第二种方案:使用同步方法

使用步骤:

   1.把访问了共享数据的代码抽取出来,放到一个方法中

   2.在方法上添加synchronized修饰符

格式:

  修饰符 synchronized 返回值类型 方法名(...) {

    可能会出现线程安全问题的代码(访问了共享数据的代码)

  }

同步方法的锁对象是:this

静态同步方法的锁对象不能是this,因为this是创建对象后产生的,静态方法优先于对象

静态方法的锁对象是本类的class文件对象

package com.fgy.demo03;

/**
 * 实现卖票案例
 */
public class RunnableImpl implements Runnable {
  private int ticket = 100;

  @Override
  public void run() {
    while (true) {
      payTicket();
    }
  }

  public synchronized void payTicket() {
    if (ticket > 0) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
      ticket--;
    }
  }
}

解决线程安全问题的第三种方案:使用lock锁

使用步骤:

   1.在成员位置创建ReenterantLock对象

   2.在可能出现安全问题的代码前调用Lock接口中的方法lock()获取锁

   3.在可能出现安全问题的代码后调用Lock接口中的方法unlock()释放锁

package com.fgy.demo04;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 实现卖票案例
 */
public class RunnableImpl implements Runnable {
  private int ticket = 100;
  Lock l = new ReentrantLock();

  /*@Override
  public void run() {
    while (true) {
      l.lock();

      if (ticket > 0) {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
        ticket--;
      }

      l.unlock();
    }
  }*/

  @Override
  public void run() {
    while (true) {
      l.lock();

      if (ticket > 0) {
        try {
          Thread.sleep(100);
          System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
          ticket--;
        } catch (InterruptedException e) {
          e.printStackTrace();
        } finally {
          // 无论程序是否发生异常都会释放锁
          l.unlock();
        }
      }
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java线程安全问题小结_动力节点Java学院整理

    浅谈java内存模型 不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的.其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改.总结java的内存模型,要解决两个主要的问题:可见性和有序性.我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的.JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节,对于java开发人员,要清楚在jvm内存模型的基础上,如果解决多线程的可见性和有序性. 那么,何谓

  • 实例解析Java中的synchronized关键字与线程安全问题

    首先来回顾一下synchronized的基本使用: synchronized代码块,被修饰的代码成为同步语句块,其作用的范围是调用这个代码块的对象,我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步.这叫减小锁的粒度,使代码更大程度的并发. synchronized方法,被修饰的方法成为同步方法,其作用范围是整个方法,作用对象是调用这个方法的对象. synchronized静态方法,修饰一个static静态方法,其作用范围是整个

  • Java银行取钱线程安全问题实例分析

    本文实例讲述了Java银行取钱线程安全问题.分享给大家供大家参考,具体如下: 一 定义一个账户类 public class Account { // 封装账户编号.账户余额的两个成员变量 private String accountNo; private double balance; public Account(){} // 构造器 public Account(String accountNo , double balance) { this.accountNo = accountNo;

  • Java多线程模拟售票程序和线程安全问题

    Java中线程部分知识中,售票程序非常经典.程序中也有一些问题存在! 需求:模拟3个窗口同时在售100张票. 问题1:为什么100张票被卖出了300张票? 原因:因为tickets是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份. 解决方案:把tickets票数共享出来给三个线程对象使用.使用static修饰. 问题2: 出现了线程安全问题 ? 线程安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的. java线程同步机制的方式: 方式一:同

  • Java 单例模式线程安全问题

    Java 单例模式线程安全问题 SpringIOC容器默认提供bean的访问作用域是单例模式.即在整个application生命周期中,只有一个instance.因此在多线程并发下,会有线程安全风险.我们在MVC框架下的servlet就是线程安全的.由于该servlet是在客户端,多并发相对少,但是对于web service端,需要考虑到. ThreadLocal类:为每一个线程提供了一个独立的变量(实例)副本,从各将各个不同的实例访问isolation. 在同步锁机制中,后来者线程等待先行线程

  • Java ThreadLocal 线程安全问题解决方案

    一.线程安全问题产生的原因 线程安全问题都是由全局变量及静态变量引起的 二.线程安全问题 SimpleDateFormate sdf = new SimpleDateFormat();使用sdf.parse(dateStr);sdf.format(date);在sdf内有一个对Caleadar对象的引用,在源码sdf.parse(dateStr);源码中calendar.clear();和calendar.getTime(); // 获取calendar的时间 如果 线程A 调用了 sdf.pa

  • 完美解决Java中的线程安全问题

    给出一个问题,如下: 解决方案如下: public class Demo_5 { public static void main(String[] args) { //创建一个窗口 TicketWindow tw1=new TicketWindow(); //使用三个线程同时启动 Thread t1=new Thread(tw1); Thread t2=new Thread(tw1); Thread t3=new Thread(tw1); t1.start(); t2.start(); t3.s

  • 基于java线程安全问题及原理性分析

    1.什么是线程安全问题? 从某个线程开始访问到访问结束的整个过程,如果有一个访问对象被其他线程修改,那么对于当前线程而言就发生了线程安全问题:如果在整个访问过程中,无一对象被其他线程修改,就是线程安全的. 2.线程安全问题产生的根本原因 首先是多线程环境,即同时存在有多个操作者,单线程环境不存在线程安全问题.在单线程环境下,任何操作包括修改操作都是操作者自己发出的,操作者发出操作时不仅有明确的目的,而且意识到操作的影响. 多个操作者(线程)必须操作同一个对象,只有多个操作者同时操作一个对象,行为

  • 如何实现Java线程安全问题

    这篇文章主要介绍了如何实现Java线程安全问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 解决线程安全问题的第一种方案:使用同步代码块 格式: synchronized(锁对象) { 可能会出现线程安全问题的代码(访问了共享数据的代码) } 注意:代码块中的锁对象,可以是任意对象,但必须保证多个线程之间使用的是同一个 锁对象的作用是把同步代码块锁住,同一时间只能让一个线程在同步代码块中执行 package com.fgy.demo02; /

  • Java线程安全问题的解决方案

    目录 线程安全问题演示 解决线程安全问题 1.原子类AtomicInteger 2.加锁排队执行 2.1 同步锁synchronized 2.2 可重入锁ReentrantLock 3.线程本地变量ThreadLocal 总结 前言: 线程安全是指某个方法或某段代码,在多线程中能够正确的执行,不会出现数据不一致或数据污染的情况,我们把这样的程序称之为线程安全的,反之则为非线程安全的.在 Java 中, 解决线程安全问题有以下 3 种手段: 使用线程安全类,比如 AtomicInteger. 加锁

  • Java中线程安全问题

    目录 一.线程不安全 二.那些情况导致了线程不安全? 三.Java中解决线程不安全的方案 1.volatile"轻量级"解决线程不安全 2.synchronized自动加锁 四.公平锁与非公平锁机制 五.volatile和synchronized的区别 六.synchronized和Lock的区别 一.线程不安全 多线程的执行环境中,程序的执行结果和预期的结果不符合,这就称为发生了线程不安全现象 二.那些情况导致了线程不安全? 大致分为以下5种情况: (1)CPU抢占执行 (无法解决)

  • 关于java中线程安全问题详解

    目录 一.什么时候数据在多线程并发的环境下会存在安全问题? 二.怎么解决线程安全问题? 三.银行 取钱/存钱 案例 为什么会出现线程安全问题 四.总结 一.什么时候数据在多线程并发的环境下会存在安全问题? 三个条件: 条件1:多线程并发. 条件2:有共享数据. 条件3:共享数据有修改的行为. 满足以上3个条件之后,就会存在线程安全问题. 二.怎么解决线程安全问题?         线程排队执行.(不能并发).用排队执行解决线程安全问题.这种机制被称为:线程同步机制. 三.银行 取钱/存钱 案例

随机推荐