This repository was archived by the owner on Sep 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathDay19—线程的同步机制、线程的基本操作.java
66 lines (58 loc) · 3.52 KB
/
Day19—线程的同步机制、线程的基本操作.java
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
今日内容:
1.线程的基本操作
2.线程的同步机制
3.网络编程的常识
1.线程的基本操作
static void yield() — 用于使得当前线程让出 CPU 的执行权转而去执行其他线程
static void sleep(long millis) — 用于让当前线程休眠参数指定的毫秒数
static void sleep(long millis , int nanos) — 用于休眠参数指定的毫秒加上纳秒
void interrupt() — 用于打断正在睡眠的线程(了解)
int getPriority() — 用于获取当前线程的优先级
int setPriority() — 用于设置当前线程的优先级
— 优先级高的线程并不一定先执行,只是获取时间片的机会更多一些而已
void join() — 用于等待调用的对象代表的线程终止
void join(long millis) — 用于等待该线程终止的最长时间为参数指定的毫秒
void join(long millis, int nanos) — 用于等待的时间为参数指定的毫秒加纳秒
void setDaemon(boolean on) — 用于将线程设置为守护线程
boolean isDaemon() — 用于判断该线程时候为守护线程
— 当所有非守护线程结束时,守护线程也就随之结束,如:垃圾回收线程
2.线程的同步机制(重点)
2.1 基本概念
当多个线程同时访问同一个共享资源时,可能会造成数据的不一致等问题,此时就需要进行线程之间的协调和通信,该机制就叫做线程的同步机制。
2.2 解决方案
由案例可知:当线程一还没有取款结束时,线程就过来取款会导致数据不一致的问题。
解决方案:让线程一取款结束后在执行线程二即可,也就是将线程的并发改成串行即可。
建议:串行会导致效率比较低,因此建议能不用则尽量不用。
2.3 实现方法
在 Java 语言中使用 synchronized 关键字来保证线程执行的原子性,具体方式如下:
(1)使用同步语句块的方式
synchronized(引用/对象){
编写所有需要锁定的代码块;
}
该用法通常用于锁定具体某一段代码的场合中,尽量减少锁定的范围。
(2)使用同步方法的方式
直接使用 synchronized 关键字修饰整个方法,表示锁定方法的所有代码(常见)
该方法本子上等价于 synchronized(this){} 的方式
2.4 实现原理
当启动多个线程后各个线程独立运行,并同时去抢占共享资源,若其中一个线程抢到资源则进行加锁处理,其他线程进入阻塞状态,知道该线程执行完毕所有锁定的代码并释放同步锁后,其他线程才能再次抢占共享资源,抢不到的线程继续阻塞。
只有锁定的代码是被多个线程依次串行执行的,其他地方还是并发执行。
2.5 死锁的概念
线程一执行的代码:
void run(){
synchronized(a){ //持有同步锁 a,等待同步锁 b
synchronized(b){}
}
}
线程二执行的代码:
void run(){
synchronized(b){ //持有同步锁 b,等待同步锁 a
synchronized(a){}
}
}
经验分享:
在以后的开发中尽量不要使用同步语句块的嵌套使用,避免死锁的发生。
2.6 Object类中的方法
void wait() — 用于让当前正在执行的线程进入等待状态,直到其他线程调用 notify() 或 notifyAll() 方法为止
void wait(long timeout) — 让线程进入等待状态,直到其他线程调用上述方法或参数指定的时间到了为止,然后接触阻塞状态
void notify() — 用于唤醒等待的任意一个线程
void notifyAll() — 用于唤醒等待的所有线程