Java——多线程(9/9):(了解)乐观锁(介绍需求CAS算法)、多线程练习题

目录

乐观锁

介绍

需求

CAS算法

多线程练习题

线程类

main 


乐观锁

介绍

  • 悲观锁:上来就加锁,没有安全感。每次只能一个线程进入访问完毕后,再解锁。线程安全,性能较差!
  • 乐观锁:一开始不上锁,认为是没有问题的,大家一起跑,等要出现线程安全问题的时候才开始控制。线程安全,性能较好。

需求

1个变量,100个线程,每个线程对其加100次。

public class MyRunnable implements Runnable{
    private int count;  //记录浏览人次

    @Override
    public void run() {
        //100次
        for (int i = 0; i < 100; i++) {
            synchronized (this){
                System.out.println(Thread.currentThread().getName() +
                        " count =======>" + (++count));
            }
        }
    }
}
public class Test1 {
    public static void main(String[] args) {
        //需求1:1个变量,100个线程,每个线程对其加100次。
        Runnable target = new MyRunnable();
        for(int i = 1; i <= 100;i++){
            new Thread(target).start();
        }
    }
}

运行结果:


这段代码一开始就上了锁,属于典型的悲观锁,所以是一个一个地去竞争锁,其他进程都要排队;排队次数太多,性能很差。


因为性能太差,所以我们不用悲观锁,采用CAS算法(比较和交换算法)。

CAS算法

这个算法的基本思路:

  1. 先拿到数据初始的值,将其修改之后;
  2. 再回到数据初始地址,比较初始值是否被修改;
  3. 如果被修改,则撤销这次修改值的操作;
  4. 如果未被修改,则执行这次修改操作。

代码示例:

import java.util.concurrent.atomic.AtomicInteger;

public class MyRunnable2 implements Runnable{
    //整数修改的乐观锁:原子类实现的。
    private AtomicInteger count = new AtomicInteger();

    @Override
    public void run() {
        //100次
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() +
                    " count ========>" + count.incrementAndGet() );
        }
    }
}

多线程练习题

目标:有100份礼品,小红,小明两人同时发送,当剩下的礼品小于10份的时候则不再送出。

利用多线程模拟该过程并将线程的名称打印出来。并最后在控制台分别打印小红,小明各自送出多少份礼物。

线程类

import java.util.List;
import java.util.Random;

public class SendThread extends Thread{
    private List<String> gift;
    private int count;

    public SendThread(List<String> gift,String name){
        super(name);
        this.gift = gift;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        //小明、小红 发礼物出去
        //实现线程安全问题
        //注意:锁必须唯一
        Random r = new Random();
        while(true){
            synchronized (gift){
                if(gift.size() < 10){
                    break;
                }
                String rs = gift.remove(r.nextInt(gift.size()));
                System.out.println(name + "发出了:" + rs);
                count++;
            }
        }
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

main 

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Demo1 {
    public static void main(String[] args) throws Exception {
        //目标:有100份礼品,小红,小明两人同时发送,当剩下的礼品小于10份的时候则不再送出。
        //利用多线程模拟该过程并将线程的名称打印出来。并最后在控制台分别打印小红,小明各自送出多少份礼物。

        //1.拿100份礼品到程序中来
        List<String> gift = new ArrayList<>();
        String[] names = {"口红","包包","鲜花","手绳","手镯","手表"};
        Random r = new Random();
        for (int i = 0; i < 100; i++) {
            gift.add(names[r.nextInt(names.length)] + (i + 1) ); //随机添加礼物 + 礼物的序号
        }
        System.out.println(gift);

        //2.定义线程类,创建线程对象,去集合中拿礼物给别人
        SendThread xm = new SendThread(gift,"小明");
        xm.start();

        SendThread xh = new SendThread(gift,"小红");
        xh.start();

        xm.join();
        xh.join();

        System.out.println("小明发出了:" + xm.getCount() + "份礼物");
        System.out.println("小红发出了:" + xh.getCount() + "份礼物");
    }
}


END


学习自:黑马程序员——Java课程

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值