线程同步
一个多先别多个线程同时操作
队列 和 锁 来解决安全性
synchronized 一个线程所占有独立自由其他线程必须等待
存在问题:
-
一个线程有锁为导致其他需要此锁的线程挂起
-
多线程竞争下 加锁 释放锁会导致比较多的上下文切换和调度延时引起性能问题
-
一个低优先级的线程拿到锁高优先级只能挂起会导致优先级倒置,引起性能问题
锁的对象要是变化的量 增删改的对象
线程不安全例子 ABC买票 有人拿到一样的票或者拿到负数
public class UnafeBuyTicket
{
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"A").start();
new Thread(buyTicket,"B").start();
new Thread(buyTicket,"C").start();
}
}
class BuyTicket implements Runnable{
private int ticketNums = 10; //十张票
boolean flag = true;// 外部的停止方式
@Override
public void run() {
while(flag){
buy(); //调用买票
}
}
private void buy() {//是否有票
if (ticketNums<=0){
flag =false;//停止标志移位
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ " 买到第 "+ ticketNums--);
}
}
加入synchronized 关键字来实现安全
public class UnafeBuyTicket
{
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"A").start();
new Thread(buyTicket,"B").start();
new Thread(buyTicket,"C").start();
}
}
class BuyTicket implements Runnable{
private int ticketNums = 10; //十张票
boolean flag = true;// 外部的停止方式
@Override
public void run() {
while(flag){
buy(); //调用买票
}
}
private synchronized void buy() {//是否有票
if (ticketNums<=0){
flag =false;//停止标志移位
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ " 买到第 "+ ticketNums--);
}
}
ArrayList 的不安全情况 内存会相互覆盖
import java.util.ArrayList;
import java.util.List;
public class UnsafeList {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()-> {
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
加锁 锁住 变化的地方
import java.util.ArrayList;
import java.util.List;
public class UnsafeList {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
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());
}
}