线程的同步

Posted yicurtain

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程的同步相关的知识,希望对你有一定的参考价值。

线程的同步

线程的生命周期

同步

在Java中,我们通过同步机制,来解决线程的安全问题。

方法一:同步代码块

synchronized(同步监视器){

​ 需要被同步的代码

}

说明

  1. 操作共享数据的代码,即为需要被同步的代码

  2. 共享数据:多个线程共同操作的变量

  3. 同步监视器:俗称:锁。任何一个对象,都可以充当锁。

    要求:多个线程必须公用同一把锁。

举例

package com.yicurtain.THREAD;
//三个窗口卖100张票,使用同步代码块解决线程的安全问题
class window implements Runnable{
    private int ticket=100;
    Object object=new Object();
    @Override
    public void run() {
        while(true) {
            synchronized (object) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}


public class WindowTest {
    public static void main(String[] args) {
        window window = new window();

        Thread t1 = new Thread(window);
        Thread t2 = new Thread(window);
        Thread t3 = new Thread(window);

        t1.setName("线程1");
        t2.setName("线程2");
        t3.setName("线程3");

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

    }
}

方法二:同步方法

如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明为同步的.

举例

package com.yicurtain.THREAD;
//三个窗口卖100张票,使用同步方法解决线程的安全问题
class window1 implements Runnable{
    private int ticket=100;
    Object object=new Object();
    @Override
    public void run() {
        while(true) {
            show();


        }
    }
    public synchronized void show(){
        if (ticket > 0) {
            System.out.println(Thread.currentThread().getName() + ":" + ticket);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticket--;
        }
    }
}


public class WindowTest1 {
    public static void main(String[] args) {
        window1 window1 = new window1();

        Thread t1 = new Thread(window1);
        Thread t2 = new Thread(window1);
        Thread t3 = new Thread(window1);

        t1.setName("线程1");
        t2.setName("线程2");
        t3.setName("线程3");

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

    }
}

总结

  1. 同步方法仍然涉及到同步监视器,只是不需要我们显示的声明。
  2. 非静态的同步方法,同步监视器是:this
  3. 静态的同步方法,同步监视器是:当前类本身

死锁

  1. 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃
    自己需要的同步资源,就形成了线程的死锁
  2. 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于
    阻塞状态,无法继续

方式三:lock锁

  1. 实例化Reentrantlock
  2. 将要执行的代码用try{lock.lock}-finally{lock.unlock}包住
  3. 然后执行

举例

package com.yicurtain.THREAD;

import java.util.concurrent.locks.ReentrantLock;

//三个窗口卖100张票,使用lock解决线程的安全问题
class window2 implements Runnable{
    private int ticket=100;
   ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while(true) {
            try{
                lock.lock();
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + ticket);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                } else {
                    break;
                }
            }finally {
                lock.unlock();
            }

            }

    }
}

public class WindowTest2 {
    public static void main(String[] args) {
        window2 window2 = new window2();

        Thread t1 = new Thread(window2);
        Thread t2 = new Thread(window2);
        Thread t3 = new Thread(window2);

        t1.setName("线程1");
        t2.setName("线程2");
        t3.setName("线程3");

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

    }
}

以上是关于线程的同步的主要内容,如果未能解决你的问题,请参考以下文章

起底多线程同步锁(iOS)

多线程编程

第十次总结 线程的异步和同步

详解C++多线程

进程线程同步异步

配置 kafka 同步刷盘