多线程(2)

2 篇文章 0 订阅
java多线程

先聊以下CAS:CAS:compare and swap:就是比较并且交换 这里用到三个值,一个是内存里面的值,一个是预期的旧值,一个是新值,当内存里面的值等于预期的旧值的时候,便将原子值设置为新值。
下面是几种多线程的同步方式:
1.synchronized(独占锁)
2.lock(高级同步机制)
3.atomicInteger(非阻塞)
4.semaphore(高级同步对象)

synchronized:每次只允许一个线程进入

wait():让当前线程释放锁并进入阻塞状态
notify():随机唤醒一个被阻塞的线程,并将该线程放入锁等待池
notifyall():唤醒所有的被阻塞的线程,并将他们放入锁等待池

class Test{
    void show(){
       synchronized (Test.class){//这里需要一个锁对象,当一个线程进入该代码块以后,其他线程不能进如该代码块,只能再外面等待
           System.out.println("11111");
       }
    }
        
}
lock:互斥锁,比synchronized扩展性更高,但是需要手动释放锁

lock():给当前代码上锁,获取锁的线程进入并执行,没有获取锁的线程等待锁的释放
unlock():释放锁,
readlock():获取读锁
writelock():获取写锁
读锁和写锁嗾使来自ReentrantReadWriteLock类

lock.lock();//上锁,当上了锁之后,其他线程就布恩那个访问该方法处于阻塞状态
    if (single == 1) {
        System.out.print("1");
        System.out.print("1");
        System.out.print("1");
        System.out.print("1");
        System.out.println("");
        try {
            c.await();
            single = 2;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    if (single == 2) {
        c1.signal();
    }
lock.unlock();//解锁,解锁完以后,其他线程都可以进入
atomicInteger:利用了ACS对整数的操作包装为原子性,CAS便是用了atomicInteger的compareAndSet()方法

compareAndSet():比较当前值是否等于预期值,相等便将该值原子设置为新值get():获取当前值
incrementAndGet():原子上增加一个当前值,并返回一个新值

class Test{
   private AtomicInteger atomicInteger=new AtomicInteger(10);//初始值为10
   void show(){
       System.out.println(Thread.currentThread().getName()+"-----"+atomicInteger.incrementAndGet());//原子的值上加一并输出结果
   }
    public static void main(String[] args) {
       Test test=new Test();
        new Thread(){
            @Override
            public void run() {
               while (true){
                   test.show();
               }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                while (true){
                    test.show();
                }
            }
        }.start();
    }
}
semaphore:利用信号量计数器来经行多线程操作

acquire():获取许可证,并将信号量-1
release():释放许可证,并将信号量+1

下面实现一个小的上厕所实验:

class FF{
    Lock lock=new ReentrantLock();//创建一个锁对象
    Semaphore semaphore;//创建资源对象,即创建厕所数量
    boolean single[];//创建资源对象的状态,即该厕所有没有人上

    public FF(Semaphore semaphore, boolean[] single) {
        this.semaphore = semaphore;
        this.single = single;
    }
    void show() throws InterruptedException {
        semaphore.acquire();//调用acquire方法获取许可证,默认一开始是1,通俗来讲就是看看有没有空位的厕所,这里你要用厕所,所以他会-1,如过结果是0表示没有位置了,则其他线程不能进入
        int i=show1();//获取当前有空位厕所的索引
        System.out.println(Thread.currentThread().getName()+"上了"+i+"号厕所");
        Thread.sleep(1000);//相当于上厕所时间
        single[i]=false;//上完以后该厕所变为空的,所以赋值为false
        semaphore.release(); //释放许可证返回给信号量这里因为上完了所以信号量+1
    }
   int show1() {//这个是返回有空位的厕所的索引
       lock.lock();//上锁,避免你现在找的时候别人也进来找发生冲突
       int j = 0;//设有空位的厕所的索引是0
       for (int i = 0; i < single.length; i++) {
           if (single[i] != true) {
               j = i;//判断厕所有没有空位,有的话就返回i,并将该位置设为true表示有人了
               single[i] = true;
               break;
           }
       }
       lock.unlock();//释放锁,让别的人来找
       return j;
       }
      
public static void main(String[] args) {
  FF f=new FF(new Semaphore(10,true),new boolean[10]);//创建一个信号量对象,里面声明了资源数量为10就是由10个厕所,后面的true是设置该锁位公平锁,如果写false就是非公平锁。
  ExecutorService executorService = Executors.newCachedThreadPool();//创建线程池
    for (int i = 0; i < 100; i++) {  //假如有100个人同时上厕所
        executorService.execute(new Thread(){
            @Override
            public void run() {
                try {
                    f.show();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值