案例1:不安全买票,出现重复买票、或出现负数

加上 synchronized

  1. package com.pln.syn;
  2. //不安全买票
  3. //可能出现负数
  4. public class UnsafeBuyTicket {
  5. public static void main(String[] args) {
  6. BuyTicket buyTicket = new BuyTicket();
  7. new Thread(buyTicket,"小明").start();
  8. new Thread(buyTicket,"老手").start();
  9. new Thread(buyTicket,"黄牛").start();
  10. }
  11. }
  12. class BuyTicket implements Runnable{
  13. // 票
  14. private int ticketNumber = 10;
  15. boolean flag = true;
  16. @Override
  17. public void run() {
  18. while (flag){
  19. try {
  20. buy();
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. // 在private后边加上 synchronized同步方法,锁的是this
  27. //就会进行排队
  28. private synchronized void buy() throws InterruptedException {
  29. if(ticketNumber <= 0){
  30. flag = false;
  31. System.out.println(Thread.currentThread().getName()+"票卖完了");
  32. return ;
  33. }
  34. Thread.sleep(100);//模拟延时
  35. System.out.println(Thread.currentThread().getName()+"------>"+ticketNumber--);
  36. }
  37. }

image.png
加上synchronized之后:
image.png

案例二:账户余额会出现负数

  1. package com.pln.syn;
  2. //不安全取钱
  3. //两个人到银行取钱,账户
  4. public class UnsafeBank {
  5. public static void main(String[] args) {
  6. Account account = new Account("结婚基金",100);
  7. Drawing drawing = new Drawing(account,50,"小明");
  8. Drawing girlFriends = new Drawing(account,100,"girlFriends");
  9. drawing.start();
  10. girlFriends.start();
  11. }
  12. }
  13. //账户
  14. class Account {
  15. String name;//账户名字
  16. int money;//余额
  17. public Account(String name, int money) {
  18. this.name = name;
  19. this.money = money;
  20. }
  21. }
  22. //银行模拟取款
  23. class Drawing extends Thread{
  24. Account account;//账户
  25. int drawingMoney;//取了多少钱
  26. int nowMoney;//现在手里还有多少钱
  27. public Drawing(Account account, int drawingMoney,String name) {
  28. super(name);
  29. this.account = account;
  30. this.drawingMoney = drawingMoney;
  31. }
  32. public void run(){
  33. // 判断有没有钱
  34. if(account.money - drawingMoney <0){
  35. System.out.println("没有钱了");
  36. return;
  37. }
  38. try {
  39. Thread.sleep(1000);
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43. account.money = account.money - drawingMoney;
  44. nowMoney = nowMoney + drawingMoney;
  45. System.out.println(account.name+"余额"+account.money);
  46. System.out.println(Thread.currentThread().getName()+"现在手里有"+nowMoney);
  47. }
  48. }
  49. //解决问题
  50. //增加同步代码块
  51. //锁的对象是变化的量,增删改
  52. public void run(){
  53. synchronized (account){
  54. // 判断有没有钱
  55. if(account.money - drawingMoney <0){
  56. System.out.println("钱不够了,不能取钱");
  57. return;
  58. }
  59. try {
  60. Thread.sleep(1000);
  61. } catch (InterruptedException e) {
  62. e.printStackTrace();
  63. }
  64. account.money = account.money - drawingMoney;
  65. nowMoney = nowMoney + drawingMoney;
  66. System.out.println(account.name+"余额"+account.money);
  67. System.out.println(Thread.currentThread().getName()+"现在手里有"+nowMoney);
  68. }
  69. }

image.png
解决之后的输出:
image.png

案例三:线程不安全集合

package com.pln.syn;

import java.util.ArrayList;
import java.util.List;
//线程不安全集合
public class UnsafeList {
    public static void main(String[] args) throws InterruptedException {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        Thread.sleep(3000);
        System.out.println(list.size());
    }
}
//正确的修改
for (int i = 0; i < 10000; i++) {
    synchronized (list){
        new Thread(()->{
            list.add(Thread.currentThread().getName());
        }).start();
    }
}

image.png
不是10000,所以不安全,有的被覆盖了
修改正确的结果:
image.png