JAVA多线程线程同步问题

线程同步  在多线程的编程环境下,可能看着没有问题的代码在运行几千上万或者更多次后,出现了一些看着很奇怪的问题,出现这样的问题的原因就是可能会有两个或者更多个线程进入了同一块业务处理代码中导致了判断失效。为了解决这个问题,JAVA引入了同步监视器来解决这个问题。同步监视器的通用方法就是同步代码块,也就是给一块代码加了同步锁。
package cn.test.hf;

import java.math.BigDecimal;

/** * 模拟取钱操作 */public class RunnableTest implements Runnable {

private Account account;

// 当前用户想取的钱    private BigDecimal withdrawal;

public RunnableTest(Account account, BigDecimal withdrawal) {

this.account = account;        this.withdrawal = withdrawal;    }

public void run() {

// 判断当前用户取钱的数目是否超出余额        if (this.withdrawal.subtract(this.account.getHaveMoney()).doubleValue() <= 0) {

// 取钱之后将账户的余额减少            this.account.setHaveMoney(this.account.getHaveMoney().subtract(this.withdrawal));            System.out.println("当前用户" + Thread.currentThread().getName() + "取出金额" + this.withdrawal + ",取款成功!");        } else {

System.out.println("当前用户" + Thread.currentThread().getName() + "取的金额" + this.withdrawal + "超出限制!");        }    }

public static void main(String[] args) {

try {

Account account = new Account();

account.setHaveMoney(new BigDecimal(1000));            account.setRemainMoney(new BigDecimal(1000));

RunnableTest r1 = new RunnableTest(account, new BigDecimal("800"));            RunnableTest r2 = new RunnableTest(account, new BigDecimal("900"));

Thread t1 = new Thread(r1, "张三");            t1.start();            Thread t2 = new Thread(r2, "李四");            t2.start();            // 完成之后再还原        } catch (Exception e) {

}    }}

在高并发的情况下,张三和李四操作了同一个账户,可能会出现的问题是张三和李四取钱都成功了,那么账户的余额就为负数了。

处理这种问题

方法1、使用synchronized(obj)同步代码块来锁定当前的obj对象,obj就是同步监视器,任何时刻只有一个线程可以获得对同步监视器的锁定,线程操作完后释放对象锁。

代码如下:
public void run() {

synchronized (this.account) {        // 判断当前用户取钱的数目是否超出余额        if (this.withdrawal.subtract(this.account.getHaveMoney()).doubleValue() <= 0) {

// 取钱之后将账户的余额减少            this.account.setHaveMoney(this.account.getHaveMoney().subtract(this.withdrawal));            System.out.println("当前用户" + Thread.currentThread().getName() + "取出金额" + this.withdrawal + ",取款成功!");        } else {

System.out.println("当前用户" + Thread.currentThread().getName() + "取的金额" + this.withdrawal + "超出限制!");        }    }}

方法二、使用同步方法,同步方法和同步代码块对应,同步方法就是使用synchronized来修饰某个方法,对于synchronized修改的实例方法无须显示指定同步控制器,同步方法的同步监视器就是当前对象,也就是this,不可变类总是线程安全的,可变类不是线程安全的,所以可以通过synchronized来修饰对应的set方法来控制多线程并发访问。
时间: 2024-10-16 21:54:11

JAVA多线程线程同步问题的相关文章

Java多线程 线程同步

如果你正在写一个变量,它可能接下来将被另一个线程读取,或者正在读取一个上一次已经被另一个线程写过的变量,那么你需要使用同步,并且,读写线程都必须用相同的监视器锁同步.--Brain同步规则 synchronized 所有对象都自动含有单一的锁,当在调用一个对象的任意synchronized方法时,此对象将被加锁. 对于某个特定对象来说,所有的synchronized方法共享同一个锁.所以某个线程在访问对象的一个synchronized方法时,其他线程访问该对象的任何synchronized方法都

Java多线程——线程同步

在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系.可是有的时候,可能存在多个线程多同一个数据进行操作,这样,可能就会引用各种奇怪的问题.现在就来学习多线程对数据访问的控制吧. 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问.   一.多线程引起的数据访问安全问题 下面看一个经典的问题,银行取钱的问题: 1).你有一张银行卡,里面有50

Java多线程:线程同步与关键字synchronized

一.同步的特性1. 不必同步类中所有的方法, 类可以同时拥有同步和非同步方法.2. 如果线程拥有同步和非同步方法, 则非同步方法可以被多个线程自由访问而不受锁的限制. 参见实验1:http://blog.csdn.net/huang_xw/article/details/73185613. 如果两个线程要执行一个类中的同步方法, 并且两个线程使用相同的实例来调用方法, 那么一次只能有一个线程能够执行方法, 另一个需要等待, 直到锁被释放. 参见实验2:http://blog.csdn.net/h

Java多线程基础(四)Java传统线程同步通信技术

Java多线程基础(四)Java传统线程同步通信技术 编写代码实现以下功能 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次. 分析 1)子线程循环10次与主线程循环100次必须是互斥的执行,不能出现交叉,下面代码中通过synchronized关键字实现此要求: 2)子线程与主线程必须交替出现,可以通过线程同步通信技术实现,下面代码中通过bShouldSub变量实现此要求: 其他需要注意的地方 1)其中business变量必须声

Java多线程——线程之间的同步

Java多线程——线程之间的同步 摘要:本文主要学习多线程之间是如何同步的,以及如何使用synchronized关键字和volatile关键字. 部分内容来自以下博客: https://www.cnblogs.com/hapjin/p/5492880.html https://www.cnblogs.com/paddix/p/5367116.html https://www.cnblogs.com/paddix/p/5428507.html https://www.cnblogs.com/liu

Java 并发 线程同步

Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大多数实际的多线程应用中,两个或两个以上的线程需要共享对同一数据的存取,这将产生同步问题(可见性和同步性的丢失) 比如两个线程同时执行指令account[to] += amount,这不是原子操作,可能被处理如下: a)将account[to]加载到寄存器 b)增加amount c)将结果写回acco

多线程&线程同步

线程 程序执行过程中,并发执行的代码段. 线程之间可以共享内存. 线程安全 增加了同步处理,确保在同一时刻,只有一个线程执行同步代码. 保证线程安全的方法就是锁机制 java中的任何对象都可以作为锁对象 synchronized(lock){....} 代码块中的代码被确保同一时间只有一个线程才能执行 同步方法是用当前对象作为同步对象(this) public synchronized int getTicket(){...} synchronized关键字也能加在方法上 确保同一时间只有一个线

java 多线程—— 线程让步

java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 java 多线程—— 线程等待与唤醒 java 多线程—— 线程让步 概述 第1 部分 yield()介绍 第2 部分 yield()示例 第3 部分 yield() 与 wait()的比较 第1 部分 yield()介绍 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”

java 多线程—— 线程等待与唤醒

java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 java 多线程—— 线程等待与唤醒 概述 第1部分 wait(), notify(), notifyAll()等方法介绍 第2部分 wait()和notify()示例 第3部分 wait(long timeout)和notify() 第4部分 wait() 和 notifyAll() 第5部分