线程同步机制
①例一
源代码:
package cn.ecut.syn;
public class UnsafeBuyTicket {
public static void main(String[] args) {
ByTicket byTicket=new ByTicket();
new Thread(byTicket,"甲").start();
new Thread(byTicket,"乙").start();
new Thread(byTicket,"丙").start();
}
}
class ByTicket implements Runnable{
//票数
private int ticketNum=10;
//线程停止标志位
private boolean flag=true;
@Override
public void run() {
while(flag){
buy();
}
}
//买票方法
private synchronized void buy(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(ticketNum<=0){
flag=false;
return;
}
System.out.println(Thread.currentThread().getName()+"买到了第"+ticketNum--+"张票");
}
}
运行结果:
②例二
源代码:
package cn.ecut.syn;
public class UnsafeBank {
public static void main(String[] args) {
Accont accont=new Accont(1000,"结婚基金");
Drawing me=new Drawing(accont,50,"me");
Drawing girlFriend=new Drawing(accont,100,"girlFriend");
me.start();
girlFriend.start();
}
}
//账户
class Accont{
int money;//余额
String name;//卡名
public Accont(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行
class Drawing extends Thread{
Accont accont;//账户
int drawingMoney;//取钱金额
int nowMoney;//现在手里的金额
public Drawing(Accont accont,int drawingMoney,String name){
super(name);
this.accont=accont;
this.drawingMoney=drawingMoney;
}
//取钱
@Override
public void run() {
//同步方法synchronized默认锁的是this 可以用同步块锁任意对象 一般锁的对象是变化的量 需要增删改查的对象
synchronized(accont){
if(accont.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"余额不足,无法取钱!");
return;
}
//sleep放大问题
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
accont.money=accont.money-drawingMoney;//取钱之后余额
nowMoney=nowMoney+drawingMoney;//手里金额
System.out.println(accont.name+"余额为:"+accont.money);
System.out.println(this.getName()+"手里钱:"+nowMoney);
}
}
}
运行结果:
③例三
源代码;
package cn.ecut.syn;
import java.util.ArrayList;
import java.util.List;
//线程安全的集合
public class UnsafeList {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
for (int i = 0; i <20000 ; i++) {
new Thread(()->{
//若不加锁 则会导致线程不安全 list.size将小于20000
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
运行结果:
④例四
源代码:
package cn.ecut.syn;
import java.util.concurrent.CopyOnWriteArrayList;
//测试JUC安全类型集合
public class TestJUC {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<>();
for (int i = 0; i <10000 ; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
运行结果: