多线程同步有哪些方法?

Posted 本站大佬

tags:

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

不同步代码如下:

package com;

public class A2
    public static void main(String[] args) throws InterruptedException 
        final Blank blank = new Blank();
        Thread thread1 = new Thread(new Runnable() 
            @Override
            public void run() 
                try 
                    blank.get(100);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        );

        Thread thread2 = new Thread(new Runnable() 
            @Override
            public void run() 
                try 
                    blank.get(100);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        );

        thread1.start();
        thread2.start();
        Thread.sleep(2000);
        System.out.println(blank.look());
    


class Blank
    //    账户余额
    private int money=100;

    //    存钱
    public void put(int number)
        money = money + number;
        System.out.println("存钱当前余额"+look());
    

    //    取钱
    public void get(int number) throws InterruptedException 
        if (money < number)
            System.out.println("余额不足");
            return;
        
        Thread.sleep(1000);
        money = money - number;
        System.out.println("取钱当前余额"+look());
    

    public int look()
        return money;
    


1、使用synchronized关键字。

package com;

public class A3
    public static void main(String[] args) throws InterruptedException 
        final Blank3 blank = new Blank3();
        Thread thread1 = new Thread(new Runnable() 
            @Override
            public void run() 
                try 
                    blank.get(100);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        );

        Thread thread2 = new Thread(new Runnable() 
            @Override
            public void run() 
                try 
                    blank.get(100);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        );

        thread1.start();
        thread2.start();
        Thread.sleep(2000);
        System.out.println(blank.look());
    


class Blank3
    //    账户余额
    private int money=100;

    //    存钱
    public synchronized void put(int number)
        money = money + number;
        System.out.println("存钱当前余额"+look());
    

    //    取钱
    public synchronized void get(int number) throws InterruptedException 
        if (money < number)
            System.out.println("余额不足");
            return;
        
        Thread.sleep(1000);
        money = money - number;
        System.out.println("取钱"+number+"当前余额"+look());
    

    public synchronized int look()
        return money;
    



2、wait和notify

package com;

public class A4 
    public static void main(String[] args) throws InterruptedException 
        GetAndSet getAndSet = new GetAndSet();
        GetThread getThread1 = new GetThread(getAndSet);
        GetThread getThread2 = new GetThread(getAndSet);
        GetThread getThread3 = new GetThread(getAndSet);
        GetThread getThread4 = new GetThread(getAndSet);
        SetThread setThread1 = new SetThread(getAndSet);
        getThread1.start();
        getThread2.start();
        getThread3.start();
        getThread4.start();
        Thread.sleep(1000);
        setThread1.start();
    


class GetThread extends Thread
    private GetAndSet getAndSet;

    public GetThread(GetAndSet getAndSet) 
        this.getAndSet = getAndSet;
    

    @Override
    public void run() 
        try 
            getAndSet.Get();
         catch (InterruptedException e) 
            e.printStackTrace();
        
    


class SetThread extends Thread
    private GetAndSet getAndSet;

    public SetThread(GetAndSet getAndSet) 
        this.getAndSet = getAndSet;
    

    @Override
    public void run() 
        try 
            getAndSet.Set();
         catch (InterruptedException e) 
            e.printStackTrace();
        
    


class GetAndSet
    private int singal;

    public synchronized void Get() throws InterruptedException 
        System.out.println("进入Get");
        if (singal != 1)
            System.out.println(Thread.currentThread().getName());
            wait();
        
        System.out.println("结束Get");
    

    public synchronized void Set() throws InterruptedException 
        System.out.println("进入Set");
        singal = 1;
        Thread.sleep(4000);
        notify();
        notifyAll();
        System.out.println("结束Set");
    



3、使用特殊域变量volatile实现线程同步。
3.使用特殊域变量(volatile)实现线程同步

  • a.volatile关键字为域变量的访问提供了一种免锁机制,
  • b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,
  • c.因此每次使用该域就要重新计算,而不是使用寄存器中的值
  • d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量
    ————————————————
    版权声明:本文为CSDN博主「北漂的橙子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/w893433055/article/details/85394588
package com;

public class A5
    public static void main(String[] args) 
        final Blank5 blank5 = new Blank5();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank5.setMoney(80);
            
        ).start();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank5.setMoney(80);
            
        ).start();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank5.setMoney(80);
            
        ).start();
    


class Blank5
    private volatile int money = 100;

    public void setMoney(int number)
        if (money >= number)
            money = money - number;
            System.out.println("取出了"+number+"剩余"+money);
        
            System.out.println("余额不足");
        
    



4、使用可重入锁实现线程同步。

package com;

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

public class A6 
    public static void main(String[] args) 
        Blank6 blank6 = new Blank6();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank6.setMoney(80);
            
        ).start();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank6.setMoney(80);
            
        ).start();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank6.setMoney(80);
            
        ).start();
    


class Blank6
    private int money = 100;
    private Lock lock = new ReentrantLock();
    public void setMoney(int number)
        lock.lock();
        try
            if (money >= number)
                money = money - number;
                System.out.println("取出了"+number+"剩余"+money);
            else 
                System.out.println("余额不足");
                return;
            
        finally 
            lock.unlock();
        
    



5、使用局部变量实现线程同步。
五、使用ThreadLocal管理局部变量实现线程同步
ThreadLocal管理变量,则每一个使用该变量的线程都获得一个该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的副本,而不会对其他线程产生影响。
ThreadLocal类常用的方法:
1、get():返回该线程局部变量的当前线程副本中的值。
2、initialValue():返回此线程局部变量的当前线程的”初始值“。
3、remove():移除此线程局部变量当前线程的值。
4、set(T value):将此线程局部便利啊ing的当前线程副本中的值设置为指定值value。
https://blog.csdn.net/zhaojw_420/article/details/67823750
http://www.javashuo.com/article/p-sxmqgikl-hx.html

package com;

public class A7 
    public static void main(String[] args) throws InterruptedException 
        Blank7 blank7 = new Blank7();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank7.setMoney(80);
            
        ).start();
        Thread.sleep(1000);
        blank7.getMoney();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank7.setMoney(80);
            
        ).start();
        Thread.sleep(1000);
        blank7.getMoney();
        new Thread(new Runnable() 
            @Override
            public void run() 
                blank7.setMoney(80);
            
        ).start();
    


class Blank7
    private static ThreadLocal<Integer> money = new ThreadLocal<Integer>()
        @Override
        protected Integer initialValue() 
            return 100;
        
    ;

    public void getMoney()
        System.out.println(money.get());
    

    public void setMoney(int number)
        if (money.get() - number >= 0)
            money.set(money.get()-number);
            System.out.println("取出了"+number+"剩余"+money.get());
        else 
            System.out.println("余额不足");
            return;
        
    

6、使用阻塞队列实现线程同步。
7、使用原子变量实现线程同步。
https://blog.csdn.net/kehyuanyu/article/details/24797129

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

java多线程有几种实现方法?线程之间如何同步

多线程同步有哪些方法?

java 多线程同步常用的3种方法

Java 多线程同步的五种方法

Linux 线程同步都有哪些方法?

java线程之线程同步