线程中的锁

互斥锁

每一个对象都对应一个可称为“互斥锁”的标记,这个标记用来保证任意时刻,只有一个线程可以访问该对象,但是会导致执行效率比较低,同步方法的锁可以是this,也可以是其他对象,同步方法的锁为当前类的本身。上面买票的问题可以是this本身,也可以object,但是必须同一个对象,不可以是new的多个对象。

如果在静态代码中,必须当前对象

1
2
3
4
5
6
7
8
9
10
11
12
13
class AA implements Runnable{

public static void sell() {
synchronized (AA.class){

}
}

@Override
public void run() {

}
}

线程死锁

多线程占用对方的资源,但是不肯相让,导致了死锁。线程一直得不到资源,而一直在相互等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Block block=new Block(true);
Block block1=new Block(false);
block.start();
block1.start();
}
}
class Block extends Thread{
boolean flag;
static Object object1=new Object();
static Object object2=new Object();
public Block(boolean flag){
this.flag=flag;
}
@Override
public void run() {
if (flag){
synchronized (object1){
System.out.println("a我进入到了1");
synchronized (object2){
System.out.println("a我进入到了2");
}
}
}
else {
synchronized (object2) {
System.out.println("b我进入到了2");

synchronized (object1) {
System.out.println("b我进入到了1");
}
}
}
}
}

image-20220318140102914

可以看到程序一直卡在这里等待对方释放资源

释放锁

  1. 当前线程的同步方法,同步代码块执行结束(正常的执行结束)
  2. 当前线程在同步代码块,同步方法中遇到return,break(不得已而出来)
  3. 当前线程在同步代码块,或者方法遇到了未处理的错误或者异常,导致异常结束
  4. 当前线程在同步代码块,同步方法中执行了对象的wait方法,当前线程暂停,注意但是sleep方法不会释放锁
  • 不会释放锁:线程执行同步代码块或者同步方法时,程序调用sleep,yield方法会暂停当前线程的执行,不会释放锁
  • 线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.Scanner;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Num num=new Num();
num.start();

Scanner scanner=new Scanner(System.in);
while (true) {
String letter = scanner.next();
if (letter.equals("Q")) {
System.out.println("程序结束");
num.flag=false;
break;
}
}
}
}
class Num extends Thread{
boolean flag=true;

@Override
public void run() {
while (flag){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Math.round(Math.random()*100));
}
}
}

image-20220318142935716

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* @author zss
*/
public class Test {
public static void main(String[] args) {
Credit credit=new Credit();
Thread thread=new Thread(credit);
Thread thread1=new Thread(credit);
thread.start();
thread1.start();
}
}
class Credit implements Runnable{
double balance=1000.00;
static Object object=new Object();
@Override
public void run() {
while (true){
synchronized (object){
if (balance<=0){
System.out.println("您的余额不足");
break;
}

balance=balance-100;
System.out.println(Thread.currentThread().getName()+"取出100元,还剩"+balance);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}
}

image-20220318144512275