Java多线程(二)
文章目录
四、线程的同步
4.1 线程同步的引入:
- 多线程出现了安全问题。
- 问题的原因: 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。例如:买票问题、银行卡消费问题等等。
- 解决办法: 对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。
所以,Java 对于多线程的安全问题提供了专业的解决方式:同步机制。
4.2 线程同步的方式之一:同步代码块
- 语法格式:
synchronized (对象/同步监视器){
//得到对象的锁,才能操作同步代码
// 需要被同步的代码
}
说明:
(1)操作共享数据的代码,即为需要被同步的代码。 --> 不能包含代码多了,也不能包含代码少了。
(2)共享数据:多个线程共同操作的变量。
(3)同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
(4)要求:多个线程必须要共用同一把锁。
- 使用同步代码块解决在实现 Runnable 接口的方式创建多线程的线程安全问题
// 例子:创建三个窗口卖票,总票数为100张.使用实现Runnable接口的方式
class Window1 implements Runnable{
private int ticket = 100;
// Object obj = new Object();
@Override
public void run() {
// Object obj = new Object();
while(true){
// 同步代码块---begin
synchronized (this){
// 此时的this:唯一的 Window1 的对象w //方式二:synchronized (object) {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
ticket--;
} else {
break;
}
}
// 同步代码块---end
}
}
}
public class WindowTest1 {
public static void main(String[] args) {
Window1 w = new Window1();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
- 使用同步代码块解决继承 Thread 类的方式创建多线程的线程安全问题
class Window2 extends Thread{
private static int ticket = 100;
// private static Object obj = new Object();
@Override
public void run() {
while(true){
synchronized (Window2.class){
// Window2.class表示window2这一个类,只会加载一次
// 方式二:synchronized (obj){
// synchronized (this){ 错误的方式:this分别代表着t1,t2,t3三个对象
if(ticket > 0){
try {
Thread.sleep(100);