实现线程安全的3种方式

1.同步代码块:

1.1 extends Thread 使用同步代码块的方式

public class Test{
     
    public static void main(String[] args) {
     
        SynchronizedTest synchronizedTest1 = new SynchronizedTest();
        SynchronizedTest synchronizedTest2 = new SynchronizedTest();
        synchronizedTest1.setName("线程1");
        synchronizedTest2.setName("线程2");
        synchronizedTest1.start();
        synchronizedTest2.start();
    }
}
class SynchronizedTest extends Thread{
     
//类变量
    private static int i;
    @Override
    public void run() {
     
        synchronized (SynchronizedTest.class){
     
            for (;i <= 100;i++){
     
                System.out.println(getName() + ":" + i);
            }
        }
    }
}

1.2 implements Runnable 使用同步代码块的方式

public class Test{
     
    public static void main(String[] args) {
     
        ThreadTest threadTest = new ThreadTest();
        new Thread(threadTest,"线程1").start();
        new Thread(threadTest,"线程2").start();
    }
}
//输出0-100
class ThreadTest implements Runnable{
     
    private int i;
    @Override
    public void run() {
     
        synchronized (this) {
     
            for (; i <= 100; i++) {
     
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

1.3 implements Callable 使用同步代码块的方式

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class Test{
     
    public static void main(String[] args) {
     
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        FutureTask futureTask1 = new FutureTask<>(synchronizedTest);
        FutureTask futureTask2 = new FutureTask<>(synchronizedTest);
        Thread thread1 = new Thread(futureTask1, "线程1");
        Thread thread2 = new Thread(futureTask2, "线程2");
        thread1.start();
        thread2.start();
    }
}
class SynchronizedTest implements Callable{
     
    private int i;
    @Override
    public Object call() throws Exception {
     
        synchronized (this) {
     
            int sum = 0;
            for (;i <= 100;i++){
     
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName() + ":" + i);
                sum += i;
            }
            return sum;
        }
    }
}

1.4 线程池 使用同步代码块的方式

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test{
     
    public static void main(String[] args) {
     
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        executorService.submit(synchronizedTest);
        executorService.submit(synchronizedTest);
        executorService.shutdown();
    }
}
class SynchronizedTest implements Runnable{
     
    private int i;
    @Override
    public void run() {
     
        synchronized (this) {
     
            for (;i <= 100;i++){
     
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

2.同步方法

例子:
使用线程池来调用线程,并使用同步方法的方式来实现线程安全

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test{
     
    public static void main(String[] args) {
     
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        executorService.submit(synchronizedTest);
        executorService.submit(synchronizedTest);
        executorService.shutdown();
    }
}
class SynchronizedTest implements Runnable{
     
    private int i;
    @Override
    public void run() {
     
        show();
    }
    public synchronized void show(){
     
        for (;i <= 100;i++){
     
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

3.同步锁(Lock)

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test{
     
    public static void main(String[] args) {
     
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        executorService.submit(synchronizedTest);
        executorService.submit(synchronizedTest);
        executorService.shutdown();
    }
}
//使用Lock来实现线程安全
class SynchronizedTest implements Runnable{
     
    //1.创建ReentrantLock实现类对象
    private Lock lock = new ReentrantLock();
    private int i;
    @Override
    public void run() {
     
        lock.lock();//上锁
        for (;i <= 100;i++){
     
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
        lock.unlock();//解锁
    }

}

总结: 操作共享数据的代码,即为需要被同步的代码

释放同步监视器的锁定情况:

1.当前线程在同步方法或者同步代码块执行结束

2.当前线程在同步方法或者同步代码块中遇到break,return终止了该方法

3.当前线程在同步方法或者同步代码块出现了Exception或者Error

4.当前线程在同步方法或者同步代码块,同步监视器的对象执行了wait()方法

下面线程不会释放同步监视器:

1.当前线程在同步方法或者同步代码块,程序调用Thread.sleep(),Thread.yield(),来暂停当前线程,不会释放锁

2.当前线程在执行同步代码块时,其他线程调用了该线程的suspend(),该线程挂起,该线程不会释放锁

线程同步避免发生死锁

死锁:当两个线程相互等待对方释放同步监视器就会发生死锁

你可能感兴趣的:(javaSE,java)