Java线程安全问题,解决线程同步问题的方法有哪些
第一种方法:同步代码块:
功能:用线程安全锁定核心代码。
原理:一次只能有一个线程进入,执行后会自行解锁,让其他线程进入执行。
锁需求:理论上,锁对象与当前同时执行的线程是同一个对象。
缺点:会干扰其他无关线程的执行。
所以这只是理论上的,可以理解,现实中不会用到。
类多线程_4线程同步{ public static void main(string[]args){//定义线程类并创建一个共享帐户对象accountA=new account (ABC ,10000);//创建两个thread对象new drawthread(a,晓明)。start()取钱;新drawthread(a,‘小红’)。start();} }//取款的线程类{//接收处理的账户对象,私人账户accpublic draw thread(ACC ACC,String name){ super(name);this.acc=acc} public void run(){ //取款ACC . draw money(10000);}}class account{私有字符串cartId私人双钱;//账户余额public count(){ } public count(string cartid,double money){ this . cartid=cartid;this.money=钱;}公共字符串getCartId(){ return cartId;} public void setCartId(String cartId){ this . cartId=cartId;} public double getMoney(){ return money;} public void set money(double money){ this . money=money;} public void draw money(double money){//Get谁先去取钱,线程名是人名string name=thread . current thread()。getname();//同步代码块//功能:锁定线程安全的核心代码。//原理:一次只能有一个线程进入,执行后会自行解锁,让其他线程进入执行。//锁对象要求:理论上,锁对象应该是当前同时执行的线程的同一个对象。//缺点:会干扰其他无关线程的执行。同步(满足安全性){/。无意义//判断账户是否有足够的钱if(this.money=money){ //取钱System.out.println(name )取钱成功,取: money ;//更新金额this . money-=money;System.out.println(取款后剩余的名称: this . money );}else{ //余额不足System.out.println(name )取钱,余额不足! );}}}}关于规范:建议使用共享资源作为锁对象。
建议将其用作实例化方法的锁对象。
对于静态方法,建议使用字节码(类名。class)对象作为锁对象。
//上接前面的代码//实例化方法建议用this作为锁对象synchronized (this) {//判断账户是否有足够的钱if(this.money=money){ //取款System.out.println(name )取款成功,取: money ;//更新金额this . money-=money;System.out.println(nam
e+"取钱后剩余:"+this.money); }else{ //余额不足 System.out.println(name+"来取钱,但余额不足!"); } }
//静态方法建议使用类名.class作为锁对象//每次只有一个线程能锁这个类,而类也是唯一的 public static void run(){ synchronized(account.class){ } }
第二种方法:同步方法
//同步方法 public synchronized void drawmoney(double money) { //先获取是谁来取钱,线程名即是人名 String name=Thread.currentThread().getName(); //判断账户是否够钱 if(this.money>=money){ //取钱 System.out.println(name+"来取钱成功,取了:"+money); //更新金额 this.money-=money; System.out.println(name+"取钱后剩余:"+this.money); }else{ //余额不足 System.out.println(name+"来取钱,但余额不足!"); } }
那么同步代码块和同步方法哪个好一点呢?
答案是:同步代码块
因为同步代码块锁的范围更小一点,同步方法锁的范围更大一点
但其实在现实中同步方法用的更多一点,因为代码简洁好写一点,更方便
第三种方法:Lock锁
JDK5后出现,更加灵活方便
Lock是接口不能直接实例化,我们需要采用它的实现类ReentrantLock来构建Lock锁对象
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class 多线程_4线程同步Lock锁 { public static void main(String[] args) { //定义线程类,创建一个共享的账户对象 account a=new account("abc",10000); //创建两个取钱的线程对象 new drawthread(a,"小明").start(); new drawthread(a,"小红").start(); }}//取钱的线程类class drawthread2 extends Thread{ //接收处理的账户对象 private account acc; public drawthread2(account acc,String name){ super(name); this.acc=acc; } public void run(){ //取钱 acc.drawmoney(10000); }}class account2{ private String cartId; private double money;//账户余额 //final修饰后:锁对象是唯一的和不可替换的//Lock是接口不能直接实例化,我们需要采用它的实现类ReentrantLock来构建Lock锁对象 private final Lock lock=new ReentrantLock(); public account2() { } public account2(String cartId, double money) { this.cartId = cartId; this.money = money; } public String getCartId() { return cartId; } public void setCartId(String cartId) { this.cartId = cartId; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } public void drawmoney(double money) { //先获取是谁来取钱,线程名即是人名 String name=Thread.currentThread().getName(); lock.lock();//上锁 //判断账户是否够钱 try { if(this.money>=money){ //取钱 System.out.println(name+"来取钱成功,取了:"+money); //更新金额 this.money-=money; System.out.println(name+"取钱后剩余:"+this.money); }else{ //余额不足 System.out.println(name+"来取钱,但余额不足!"); } //防止代码出现bug而不能解锁 } finally { lock.unlock();//解锁 } }}
到此这篇关于Java使用线程同步解决线程安全问题详解的文章就介绍到这了,更多相关Java线程同步内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。