CopyOnWriteArrayList是:java.util.concurrent包下的安全的数组
public class Test {
public static void main(String[] args) {
CopyOnWriteArrayList<String> List = new CopyOnWriteArrayList<>();
for (int i = 0; i < 5000; i++) {
new Thread(()->{
List.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(List.size());
}
}
一、死锁
多个线程各自占有一些共享资源
,
并且互相等待其他线程占有的资源才能运行
,
而 导致两个或者多个线程都在等待对方释放资源 ,
都停止执行的情形
.
某一个同步块 同时拥有 “
两个以上对象的锁
”
时
,
就可能会发生
“
死锁
”
的问题
产生死锁的四个必要条件:
- 1. 互斥条件:一个资源每次只能被一个进程使用。
- 2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。(例子)
- 3. 不剥夺条件 : 进程已获得的资源,在末使用完之前,不能强行剥夺。
- 4. 循环等待条件 : 若干进程之间形成一种头尾相接的循环等待资源关系
public class TestDeadLock {
public static void main(String[] args) {
new Makeup(1,"a").start();
new Makeup(0,"b").start();
}
}
class Lipstick{
}
class Mirror{
}
class Makeup extends Thread{
int choice;//选择
String name;
Makeup(int choice,String name){
this.choice =choice;
this.name=name;
}
//资源只有一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
@Override
public void run() {
//化妆
try {
mkup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void mkup() throws InterruptedException {
if(choice==0){
synchronized (lipstick){
System.out.println(this.name+"获得口红的锁");
Thread.sleep(100);
}
synchronized (mirror){
System.out.println(this.name+"获得镜子的锁");
}
}
if(choice==1){
synchronized (mirror){
System.out.println(this.name+"获得镜子的锁");
Thread.sleep(100);
}
synchronized (lipstick){
System.out.println(this.name+"获得口红的锁");
}
}
}
}
二、Lock锁(显示的同步锁)
-
从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对 象来实现同步。同步锁使用Lock对象充当 java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。
-
锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开 始访问共享资源之前应先获得Lock对象
-
ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语 义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁
-
-
package TestSynchronized; import java.util.concurrent.locks.ReentrantLock; public class TestLock { public static void main(String[] args) { Ticket T = new Ticket(); Thread t1 = new Thread(T,"小王"); Thread t2 = new Thread(T,"小李"); Thread t3 = new Thread(T,"黄牛"); t1.start(); t2.start(); t3.start(); } } class Ticket implements Runnable{ private int nums =10; private boolean flag = true; //设置线程停止条件 ReentrantLock lock = new ReentrantLock(); @Override public void run() { try { lock.lock(); buyTicket(); } finally { lock.unlock(); } } //同步方法,锁的是this private void buyTicket() { //判断是否有票 while (flag) { if (nums <= 0) { flag = false; return; //程序结束 } //所有进程在此暂定一下,模拟延时 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //买票 System.out.println(Thread.currentThread().getName() + "抢到了第" + nums-- + "票"); } } }