多线程之线程安全
首先还是贴上原博主网址,感谢原博主的分享https://home.cnblogs.com/u/lwbqqyumidi
内容很多我借鉴到,经过理解后编辑如下:
什么是线程安全呢
就是一个线程在执行的时候,失去了cpu资源,程序去执行另外一个线程了,而该线程执行体或者说一段代码是不能间断的,间断就会产生问题,这样就会出现线程不安全的情况
看下面的例子就明白了:
1 class Account { 2 3 private String accountNo;//账号 4 private double balance;//余额 5 6 public Account() { 7 8 } 9 10 public Account(String accountNo, double balance) { 11 this.accountNo = accountNo; 12 this.balance = balance; 13 } 14 15 public String getAccountNo() { 16 return accountNo; 17 } 18 19 public void setAccountNo(String accountNo) { 20 this.accountNo = accountNo; 21 } 22 23 public double getBalance() { 24 return balance; 25 } 26 27 public void setBalance(double balance) { 28 this.balance = balance; 29 } 30 31 }
1 class DrawMoneyRunnable implements Runnable { 2 private Account account; 3 private double drawAmount;//取钱数 4 public DrawMoneyRunnable(Account account, double drawAmount) { 5 super(); 6 this.account = account; 7 this.drawAmount = drawAmount; 8 } 9 //取钱 10 public void run(){ 11 if (account.getBalance() >= drawAmount) { 12 System.out.println("取钱人:"+Thread.currentThread().getName() 13 +"取钱成功, 取出钱数为:" + drawAmount); 14 double balance = account.getBalance() - drawAmount; 15 account.setBalance(balance); 16 System.out.println("余额为:" + balance); 17 } 18 } 19 }
1 public class ThreadTest { 2 public static void main(String[] args) { 3 Account account = new Account("123456", 1000); 4 DrawMoneyRunnable drawMoneyRunnable = new DrawMoneyRunnable(account, 700); 5 Thread myThread1 = new Thread(drawMoneyRunnable); 6 Thread myThread2 = new Thread(drawMoneyRunnable); 7 myThread1.start(); 8 myThread2.start(); 9 } 10 }
运行结果,发现是有问题的,因为线程执行体中代码必须是不间断执行的,这样线程不安全....
1.同步方法
public synchronized void run(){
}
对共享资源(account对象)进行访问的方法定义中加上synchronized关键字修饰,使得此方法称为同步方法。可以简单理解成对此方法进行了加锁,其锁对象为当前方法所在的对象自身(是指该线程对象吗?)。多线程环境下,当执行此方法时,首先都要获得此同步锁(且同时最多只有一个线程能够获得),只有当线程执行完此同步方法后,才会释放锁对象,其他的线程(是指该线程类创建的其它对象吗?)才有可能获取此同步锁,以此类推...
在上例中,共享资源为account对象,当使用同步方法时,可以解决线程安全问题。只需在run()方法前加上synshronized关键字即可
上面的一段话是原博主写的,不是很理解,只要简单记住加锁后,该方法就会不间断的执行完....
2.同步代码块
有时需要的只是一段代码不间断执行,这就是同步代码块
synchronized (obj){
}
其中,obj为锁对象,一般情况下,都是选择此共享资源对象作为锁对象
如上例中,共享资源就是account对象啊,因为都是在取同一个账号的钱,所以最好选用account对象作为锁对象
也可以使用this,就是指执行run方法的该线程对象
1 public void run(){ 2 //循环取钱 3 for (int i = 0; i < 1000; i++) { 4 synchronized (this){//加锁 5 ...... 6 } 7 } 8 }
3.还有其它的等待,唤醒以后在来研究....