synchronized 和 线程状态关系
1.代码执行的前提:线程必须占有CPU
2.线程有资格竞争CPU的前提:线程是Runnable状态
0.抢锁的前提是先抢CPU
1.抢锁失败
- 状态从RUNNABLE 修改为 BLOCKED
- 线程从就绪队列移动到该锁的阻塞队列上
- 从开始请求锁到最终抢到锁,经历了沧海桑田
放一个数组,长度为100000,创建三个线程,完成这么一个任务:数组里的每个值都乘以3
class Pritice2{
private static int INDEX = 0;
private static class Monk extends Thread{
int[] array;
public Monk(int[] array) {
this.array = array;
}
@Override
public void run() {
while (INDEX < array.length){
synchronized (Monk.class) {
if (INDEX < array.length) {
array[INDEX] = array[INDEX] * 3;
INDEX++;
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
int[] array = new int[100000];
Random random = new Random(20191215);
for (int i = 0; i < array.length; i++) {
array[i] = random.nextInt(10);
}
System.out.println(Arrays.toString(array));
Monk m1 = new Monk(array);
Monk m2 = new Monk(array);
Monk m3 = new Monk(array);
m1.start();
m2.start();
m3.start();
m1.join();
m2.join();
m3.join();
System.out.println(Arrays.toString(array));
}
}
[2, 4, 0, 0, 4, 0, 8, 1, 6, 5, …
[6, 12, 0, 0, 12, 0, 24, 3, 18, 15…
是符合的
这里我讲三个点
我一开始加锁的时候,是这么写的
public void run() {
while (INDEX < array.length){
//获得锁的过程是沧海桑田
synchronized (Monk.class) {
array[INDEX] = array[INDEX] * 3;
INDEX++;
}
}
}
/*
我第一次写加锁的步骤,出现了数组下标越界
怎么理解:获得锁的过程是沧海桑田
INDEX < 长度 进入循环
比如到了下标为99999的时候,他进入循环,但是此时他不一定抢到锁了,
有可能锁被别人拿去用了
这个时候轮到他的时候,下标就越界了!!!!
*/
我第二次写了个加锁
synchronized (Pritice.class){
while (INDEX < 100000){
array[INDEX] *= 3;
INDEX++;
}
}
/*
这个貌似是没问题的,但其实也挺严重的
获得锁之后,这个人就直接全锁住,吃独食,自己给加到了100000,
别人获得锁的时候就不起作用
*/
正确写法(不忘初心,里外判断)
public void run() {
while (INDEX < array.length){
//获得锁的过程是沧海桑田
synchronized (Monk.class) {
//拿到锁之后不忘初心判断一下,如果满足,就继续算
if (INDEX < array.length) {
array[INDEX] = array[INDEX] * 3;
INDEX++;
}
}
}
}
synchronized
优点:基本有了它,线程能保证安全
缺点:效率低/不够灵活
死锁(至少两把锁)
class DeadLock{
private static Object aLock = new Object();
private static Object bLock = new Object();
private static class MyThread extends Thread{
@Override
public void run() {
synchronized (aLock){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (bLock){
System.out.println("a 吃火锅");
}
}
}
}
private static class BThread extends Thread{
@Override
public void run() {
synchronized (bLock){
synchronized (aLock){
System.out.println("b 吃火锅");
}
}
}
}
public static void main(String[] args) throws InterruptedException {
MyThread aThread = new MyThread();
BThread bThread = new BThread();
aThread.start();
Thread.sleep(2000);
bThread.start();
}
}
jconsole查看