多线程_15_并发_同步_三大经典案例

线程同步(synchronized):在一个多线程环境中,我们要保证数据的准确性和安全性,同时还要提高它的性能。
并发:指同一对象多个线程同时操作
在这里插入图片描述
不安全的案例一:12306买票

package com.cb.thread.day03;



public class UnsafeTest01 {
	
		public static void main(String[] args) {
			//一份资源
			Web12306 web = new Web12306();
			System.out.println(Thread.currentThread().getName());
			
			//三个代理 
			new Thread(web,"码畜").start(); //加上名字,区分线程
			new Thread(web,"码农").start();
			new Thread(web,"码蟥").start();
		}
	}

class Web12306 implements Runnable{
	private int ticketNums = 10; //99张票
	private boolean flag = true;
	@Override
	public void run() {
		while(flag){
			test();
		}
		
	}
	public void test(){
		if(ticketNums<0){
			flag= false;
			return;
		}
		try {
			Thread.sleep(200);//模拟延时
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//Thread.currentThread().getName()谁运行run就是代表谁
		System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);

	}
}

运行结果1:
在这里插入图片描述
运行结果2:
在这里插入图片描述
从结果上看出线程不安全,数据有负数,数据相同,负数怎么来的呢,假如就剩下最后一张票了,ABC都进来了抢票,假设B优先进来,等待了200毫秒,然后AC也进来等待了200毫秒,此时B醒了,把最后一张票拿走了,C醒了只能拿0,A醒了拿-1,就有了负值。相同票是怎么出现呢,以前说过每个线程都有自己的工作空间,它们都跟主存空间都有交互,假如A先把主存的1拷贝过来,还没来的及修改数据,B也把主存的1拷贝过来,所以就会遇到两张相同的值。

案例二:

package com.cb.thread.day03;

public class UnsafeTest02 {
	public static void main(String[] args) {
		//账户
		Account account = new Account(100, "结婚礼金");
		Drawing you = new Drawing(account, 70, "男方");
		Drawing wife = new Drawing(account, 80, "女方");
		you.start();
		wife.start();
	}
}
//账户
class Account{
	int money;//金额
	String name; //名称
	public Account(int money,String name) {
		this.money = money;
		this.name = name; 
	}
}
//模拟取款
class Drawing extends Thread{
	Account account; //取钱的账户
	int drawingMoney;//取的钱数
	int packetTotal;//口袋里面的钱
	
	
	public Drawing(Account account, int drawingMoney, String name) {
		super(name);
		this.account = account;
		this.drawingMoney = drawingMoney;
	}


	@Override
	public void run() {
		if (account.money-drawingMoney<0) {
			return;
		}
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		account.money -=drawingMoney;
		packetTotal +=drawingMoney;
		System.out.println(this.getName()+"-->"+"账户余额为"+account.money);
		System.out.println(this.getName()+"口袋里面的钱-->"+packetTotal);
	}
}

运行结果:
在这里插入图片描述
结果为-50,怎么来的呢,100-70-80=-50;

案例三:将一万个线程名字放进容器中

package com.cb.thread.day03;

import java.util.ArrayList;
import java.util.List;



public class UnsafeTest03 implements Runnable{
	static List<String> list = new ArrayList<String>();
	public static void main(String[] args) {
		
		for (int i = 0; i < 10000; i++) {
			UnsafeTest03 u03 =new UnsafeTest03();
			Thread t = new Thread(u03);
			t.start();
		}
		System.out.println(list.size());
	}

	@Override
	public void run() {
		list.add(Thread.currentThread().getName());
	}

}

运行结果:结果为9956,线程被覆盖了
在这里插入图片描述

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值