线程并发会带来同一个对象被多个线程同时操作。这里我们需要知道每个对象都有一把锁,sleep并不会使对象解锁。
线程同步的形成需要 排队+锁
sychronized有两种用法:
1. 同步方法 在方法前加关键字 sychronized,这个方法是哪个对象的,就是锁的哪个对象。
package thread;
//不安全的买票
//线程不安全,有小于等于0的数出现,
public class Demo17 {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"眉笔的我").start();
new Thread(buyTicket,"欧皇的你").start();
new Thread(buyTicket,"可恶的黄牛党").start();
}
}
class BuyTicket implements Runnable{
private int ticketNums=10;//票数
boolean flag = true;//外部停止方式
@Override
public void run() {
while (flag){
try {
buy();//买票
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void buy() throws InterruptedException {
if (ticketNums<=0){//判断是否有票
flag=false;
return;
}
Thread.sleep(100);//模拟延迟
System.out.println(Thread.currentThread().getName()+"买到了第"+ticketNums--+"张票");
}
}
取到的票号有小于等于0的数出现
加上锁后:
package thread;
//不安全的买票案例修改
public class Demo17 {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket, "眉笔的我").start();
new Thread(buyTicket, "欧皇的你").start();
new Thread(buyTicket, "可恶的黄牛党").start();
}
}
class BuyTicket implements Runnable {
private int ticketNums = 10;//票数
boolean flag = true;//外部停止方式
@Override
public void run() {
while (flag) {
try {
Thread.sleep(100);//模拟延迟
buy();//买票
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//synchronized同步方法,锁的是this
private synchronized void buy() {
if (ticketNums <= 0) {//判断是否有票
flag = false;
return;
}
System.out.println(Thread.currentThread().getName() + "买到了第" + ticketNums-- + "张票");
}
}
2. 同步代码块 记住锁的是增删改的对象

public class Demo19 {
public static void main(String[] args) {
List<String> list =new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
820





