猿来绘Java-36-解决线程安全问题

1. 创建线程的方式

创建线程的方式有四种,见之前的博文

猿来绘Java-32-创建线程的四种方式

2. 解决线程安全问题的方式

同步代码块、同步方法,都可以解决线程安全问题

不同的创建线程的方式,都可以加入同步代码块和同步方法解决线程安全问题,那么组合起来就一共有4 * 2 = 8种写法。

以下只列出4中写法:

1. 同步方法-继承Thread类

2. 同步方法-实现Runnable接口

3. 同步代码块-继承Thread类

4.同步代码块-实现Runnable接口

3.代码示例

3.1. 同步方法-继承Thread类

同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。非静态的同步方法,同步监视器是this。静态的同步方法,同步监视器是:当前类本身(Xxx.class,类Xxx加载时产生的对象,运行时类)

//SynchronizedMethodTest1.java
package com.ylaihui.thread;

class ProcMsg extends Thread{
    private static int message = 100;
    @Override
    public void run() {
        while(true){
            proc();
        }
    }
//    private synchronized void proc(){ // 同步监视器是 this, 是 t1 t2 t3
    private static synchronized void proc(){ // 同步监视器是 ProcMsg.class 对象
        if(message > 0){
            System.out.println(Thread.currentThread().getName() + ":" + message);
            message--;
        }
    }
}
public class SynchronizedMethodTest1 {
    public static void main(String[] args) {
        ProcMsg t1 = new ProcMsg();
        ProcMsg t2 = new ProcMsg();
        ProcMsg t3 = new ProcMsg();
        t1.start();
        t2.start();
        t3.start();
    }
}

3.2 同步方法-实现Runnable接口,代码中只new了一个ProcessMessage2类型的对象,该对象可以充当锁。

//SynchronizedMethodTest.java
package com.ylaihui.thread;

import static java.lang.Thread.sleep;

class ProcessMessage2 implements Runnable{
    private int message = 100;
    @Override
    public void run() {
        while(true) {
            proc();
        }
    }
    private synchronized void proc(){  // 同步监视器是 this
        try {
            sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(message > 0) {
            System.out.println("process message: " + Thread.currentThread().getName() + "-" +  message);
            message--;
        }
    }
}

public class SynchronizedMethodTest {
    public static void main(String[] args) {
        ProcessMessage2 p = new ProcessMessage2();
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(p);
        Thread t3 = new Thread(p);

        t1.start();
        t2.start();
        t3.start();
    }
}

3.3 同步代码块-继承Thread类

class ProcessMsg extends Thread{
    private static int message = 100;
    private static Object obj = new Object();
    @Override
    public void run() {
        // 方式一
//        synchronized(obj){
        // ProcessMsg 在运行时只加载一次, 在底层也是一个对象
        synchronized(ProcessMsg.class){
            while(true){
                if(message > 0 ){
                    System.out.println("process message: " + message);
                    message--;
                }else
                    break;
            }
        }
    }
}

public class ThreadSynchronizedBlock1 {
    public static void main(String[] args) {
        ProcessMsg t1 = new ProcessMsg();
        ProcessMsg t2 = new ProcessMsg();
        ProcessMsg t3 = new ProcessMsg();

        t1.start();
        t2.start();
        t3.start();
    }
}

3.4 同步代码块-实现Runnable接口

//ThreadSynchronizedBlock.java
package com.ylaihui.thread;

class ProcessMessage1 implements Runnable{
    private int message = 100;
    Object obj = new Object();
    @Override
    public void run() {

//        synchronized(obj){
        synchronized(this){
            while(true){
                if(message > 0){
                    System.out.println("process message: "+ message);
                    message--;
                }else
                    break;
            }
        }
    }
}

public class ThreadSynchronizedBlock {
    public static void main(String[] args) {
        ProcessMessage1 p = new ProcessMessage1();
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(p);
        Thread t3 = new Thread(p);

        t1.start();
        t2.start();
        t3.start();
    }
}

猜你喜欢

转载自blog.csdn.net/asdfjklingok/article/details/117950316