Java多线程(三)——多线程实现同步

 

目录

一、引言

二、synchronize同步

1、synchronize代码块

2、synchronize方法

三、lock同步

1、普通lock+condition

2、lock+condition高级应用

3、lock+读写锁

四、总结


 

一、引言

 

先介绍两个概念

线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。

同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。

为什么使用同步?

多线程给我们带来了很大的方便,但是同时也给我们带来了一个致命的问题,当我们对线程共享数据进行非原子操作时,会带来知名的错误。当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。这就是多线程同步提上议程的原因,解决多线程安全问题。

举个例子:假设银行里某一用户账户有1000元,线程A读取到1000,并想取出这1000元,并且在栈中修改成了0但还没有刷新到堆中,线程B也读取到1000,此时账户刷新到银行系统中,则账户的钱变成了0,这个时候也想去除1000,再次刷新到行系统中,账号的钱变成0,这个时候A,B都取出1000元,但是账户只有1000,显然出现了问题。针对上述问题,假设我们添加了同步机制,那么就可以很容易的解决。

tips:java1.5新引入了concurrent包,里面都是关于并发的,里面还有locks和atomic两个包,很值得学习,使用方便。

 

 

二、synchronize同步

 

1、synchronize代码块

 

这里举了个复杂点的例子,模仿的生产者消费者的模式,每次添加一个数,然后读出一个数,添加后不能再次添加,读出后不能再次读出。synchronize(this){}中this为同步锁,可以是任意对象,这里是用的该类本身,只要每次锁一样就能保证两个线程再synchronize代码块中的执行是同步的,所以每次只能读取或者添加。

wait和notify是线程等待和唤醒线程的意思,每当线程wait后被notify会从等待位置继续执行,使用这个是为了在线程中进行通信,使多个线程按照自己的想法有序执行(当添加数据线程添加后在添加该线程就会wait,当读取数据线程读取数据后就会notify添加线程继续执行)。

创建多线程类

package com.lock;

public class Testlock {

    public static void main(String [] args)
    {

        data();

    }

    /***
     * synchronize
     */
    static void data()
    {
        final DataSynchronize data=new DataSynchronize();
        new Thread(new Runnable() {
            public void run() {
                for(int i=0;i<1000000000;i++)
                {
                    data.write();

                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                for(int i=0;i<1000000000;i++)
                {
                    data.get();

                }
            }
        }).start();
    }



}

 封装的共享数据及方法类

package com.lock;

/**
 * synchronize
 * 两个线程,一个存数据一个取数据——多个线程全部互斥
 */
class DataSynchronize {
        boolean hasdata;
        int x;

    public  void write()
    {
       synchronized (this)
       {
           //有数据
           if (hasdata==true)
           {
               try {
                   this.wait();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
           //没数据
           System.out.println(Thread.currentThread().getName()+"准备添加数据");
           x=(int)(Math.random()*100000);
           try {
               Thread.sleep(100);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           System.out.println(Thread.currentThread().getName()+"添加数据"+x);
           //通过上述步骤有了数据,并唤醒取数据
           hasdata=true;
           this.notify();
       }

    }

    public  synchronized void get()
    {
        synchronized (this)
        {
            //没有数据
            if (hasdata==false)
            {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"准备读取数据");
            //x=(int)Math.random();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"读取数据为"+x);
      
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值