`
y806839048
  • 浏览: 1119562 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Lock锁和Condition条件

    博客分类:
  • lock
阅读更多

浅谈Synchronized:

  synchronized是Java的一个关键字,也就是Java语言内置的特性,如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,执行代码块时,其他线程

便只能一直等待,等待获取锁的线程释放锁,而获取锁的线程释放锁会有三种情况:

  1).获取锁的线程执行完该代码块,然后线程释放对锁的占有;

  2).线程执行发生异常,此时JVM会让线程自动释放锁;

  3).调用wait方法,在等待的时候立即释放锁,方便其他的线程使用锁.

 

Lock的特性:

  1).Lock不是Java语言内置的;

  2).synchronized是在JVM层面上实现的,如果代码执行出现异常,JVM会自动释放锁,但是Lock不行,要保证锁一定会被释放,就必须将unLock放到finally{}中(手动释放);

  3).在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetarntLock,但是在很激烈的情况下,synchronized的性能会下降几十倍;

  4).ReentrantLock增加了锁:

    a. void lock(); // 无条件的锁;

    b. void lockInterruptibly throws InterruptedException;//可中断的锁;

解释:  使用ReentrantLock如果获取了锁立即返回,如果没有获取锁,当前线程处于休眠状态,直到获得锁或者当前线程可以被别的线程中断去做其他的事情;但是如果是synchronized的话,如果没有获取到锁,则会一直等待下去;

    c. boolean tryLock();//如果获取了锁立即返回true,如果别的线程正持有,立即返回false,不会等待;

    d. boolean tryLock(long timeout,TimeUnit unit);//如果获取了锁立即返回true,如果别的线程正持有锁,会等待参数给的时间,在等待的过程中,如果获取锁,则返回true,如果等待超时,返回false;

 

Condition的特性:

    1.Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。不同的是,Object中的这些方法是和同步锁捆绑使用的;而Condition是需要与互斥锁/共享锁捆绑使用的。

    2.Condition它更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。
    例如,假如多线程读/写同一个缓冲区:当向缓冲区中写入数据之后,唤醒"读线程";当从缓冲区读出数据之后,唤醒"写线程";并且当缓冲区满的时候,"写线程"需要等待;当缓冲区为空时,"读线程"需要等待。      

      如果采用Object类中的wait(), notify(), notifyAll()实现该缓冲区,当向缓冲区写入数据之后需要唤醒"读线程"时,不可能通过notify()或notifyAll()明确的指定唤醒"读线程",而只能通过notifyAll唤醒所有线程(但是notifyAll无法区分唤醒的线程是读线程,还是写线程)。  但是,通过Condition,就能明确的指定唤醒读线程。

 

synchronized{

wait();

notify();

}

==

lock{

condition.wait()'

condition.single();

 

}

unlock()

 

 

 

 

 

复制代码
package com.imooc.locks;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Task {
    
    private final Lock lock = new ReentrantLock();
    
    private final Condition addCondition = lock.newCondition();
    
    private final Condition subCondition = lock.newCondition();
    
    
    private static int num = 0;
    private List<String> lists = new LinkedList<String>();
    
    public void add() {
        lock.lock();
        
        try {
            while(lists.size() == 10) {//当集合已满,则"添加"线程等待
                addCondition.await();
            }
            
            num++;
            lists.add("add Banana" + num);
            System.out.println("The Lists Size is " + lists.size());
            System.out.println("The Current Thread is " + Thread.currentThread().getName());
            System.out.println("==============================");
            this.subCondition.signal();
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {//释放锁
            lock.unlock();
        }
    }
    
    
    public void sub() {
        lock.lock();
        
        try {
            while(lists.size() == 0) {//当集合为空时,"减少"线程等待
                subCondition.await();
            }
            
            String str = lists.get(0);
            lists.remove(0);
            System.out.println("The Token Banana is [" + str + "]");
            System.out.println("The Current Thread is " + Thread.currentThread().getName());
            System.out.println("==============================");
            num--;
            addCondition.signal();
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
}
复制代码
复制代码
package com.imooc.locks;

public class AddThread implements Runnable {
    
    private Task task;
    
    public AddThread(Task task) {
        this.task = task;
    }

    @Override
    public void run() {
        task.add();
    }

}
复制代码
复制代码
package com.imooc.locks;

public class SubThread implements Runnable {
    
    private Task task;
    
    public SubThread(Task task) {
        this.task = task;
    }

    @Override
    public void run() {
        task.sub();
    }

}
复制代码
复制代码
package com.imooc.locks;

public class TestLock {
    
    public static void main(String[] args) {
        Task task = new Task();
        
        Thread t1=new Thread(new AddThread(task));
        Thread t3=new Thread(new AddThread(task));
        Thread t7=new Thread(new AddThread(task));
        Thread t8=new Thread(new AddThread(task));
        Thread t2 = new Thread(new SubThread(task));
        Thread t4 = new Thread(new SubThread(task));
        Thread t5 = new Thread(new SubThread(task));
        Thread t6 = new Thread(new SubThread(task));
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        t6.start();
        t7.start();
        t8.start();
    }

}
分享到:
评论

相关推荐

    java中的Lock类和Condition类.docx

    Java中的Lock类与Condition类是Java并发编程的重要组成部分,它们为多线程环境下的同步提供了更为灵活和强大的控制。在JDK 1.5及之后的版本中,Lock类作为替代synchronized关键字的一种方式出现,提供了更精细的锁...

    Java并发编程(20)并发新特性-Lock锁和条件变量(

    本资源主要探讨了Java并发的新特性,特别是Lock锁和条件变量的使用。下面将详细阐述这两个概念以及如何在实际编程中应用它们。 Lock锁是Java并发库中的一个核心组件,位于java.util.concurrent.locks包下。相比传统...

    Lock锁的底层原理完整版

    Lock锁的灵活性相比synchronized更高,它支持手动获取和释放锁,能够中断的获取锁以及超时获取锁。 具体来说,Lock锁有以下主要方法:lock()用于上锁,unlock()用于解锁,tryLock()尝试非阻塞地获取锁,tryLock...

    JavaLock与Condition的理解Reentran

    **二、Condition条件对象** Condition接口是ReentrantLock的重要组成部分,它提供了比synchronized关键字的wait()和notify()更强大的控制能力。每个ReentrantLock实例都有一个默认的Condition,通过`newCondition()...

    生产者-消费者(lock和condition).zip

    4. **锁和条件控制**:在生产者和消费者操作共享资源时,必须使用`Lock`来确保互斥访问。在`try...finally`块中获取和释放锁,确保即使在异常情况下也能正确解锁。生产者和消费者线程会通过调用`Condition`的`signal...

    互斥锁和条件锁的讲解和使用

    互斥锁和条件锁是多线程编程中用于同步和通信的重要工具,它们在确保数据一致性、避免竞态条件和死锁等方面起着关键作用。本文将深入讲解这两种锁的概念、工作原理以及如何在C语言中使用它们。 首先,互斥锁(Mutex...

    Java concurrency之Condition条件_动力节点Java学院整理

    1. **同步锁**:`Condition`必须与一个`Lock`实例关联,如`ReentrantLock`。与`synchronized`不同,`synchronized`是基于 JVM 的内置锁,而`Condition`是基于用户层面的锁,提供更高级别的控制。 2. **等待/通知...

    Java多线程中Lock锁的使用总结

    Lock锁可以分为两种:独占锁和共享锁。独占锁允许多个线程访问同一个资源,但是同一时刻只能有一个线程可以访问该资源。共享锁允许多个线程同时访问同一个资源。 知识点2: Java多线程中的并发和并行 Java中的多...

    java 锁 Lock接口详解.docx

    `Condition`接口是与`Lock`相关的条件变量,它扩展了监视器的概念,允许线程在满足特定条件时等待,而不仅仅是等待锁的释放。一个`Lock`可以关联多个`Condition`对象,这样就可以根据不同的条件进行分组等待,提高了...

    linux无亲缘关系间进程同步通信实现(互斥锁+条件变量+共享内存模式)

    总结来说,互斥锁、条件变量和共享内存是Linux下实现进程间通信的关键工具,它们共同确保了多进程环境下的数据安全和程序的正确执行。通过合理地使用这些工具,开发者能够构建出高效且可靠的多进程应用程序。在实际...

    多线程+同步+锁和条件+示例

    多线程的使用涉及到一系列概念,如线程同步、锁和条件变量,这些都是确保线程安全和正确性的重要工具。 线程同步是指控制多个线程对共享资源的访问,以防止数据的不一致性和竞态条件。竞态条件是指当两个或更多线程...

    互斥锁、条件变量、信号量总结

    条件变量通常与互斥锁一起使用,以防止在检查条件和等待之间出现竞态条件。例如,在打印任务的例子中,两个线程通过共享变量、互斥锁和条件变量协同工作,交替打印数字,确保打印的顺序正确。条件变量的应用场景通常...

    第四节(Lock关键字用法)

    此外,`Lock`接口还支持更复杂的并发控制策略,如可中断的锁等待(`tryLock()`方法),以及通过`Condition`对象实现线程间的条件等待和精确唤醒。 在实际应用中,`ReentrantLock`是`Lock`接口最常见的实现,它具有...

    condition_variable源码以及详细分析.docx

    它通常与互斥锁(Mutex)和锁_guard(Lock_Guard)一起使用,以实现线程安全的数据共享。 Condition_Variable 的主要成员函数 Condition_Variable 提供了多种成员函数来实现线程同步,包括: * wait():等待条件...

    linux无亲缘关系进程间通信(互斥锁+条件变量+共享内存)

    本示例中提到的“linux无亲缘关系进程间通信”着重讲解了如何利用互斥锁(Mutex)、条件变量(Condition Variable)以及共享内存(Shared Memory)这三种机制来实现非父子进程间的同步通信。 1. **互斥锁**:互斥锁...

    C# lock一个简单实例

    在多线程环境中,多个线程可能同时尝试修改同一份数据,如果不加以控制,可能会导致数据不一致或者竞争条件(race condition)。`lock`语句通过获取一个对象的锁,阻止其他线程在同一时间对该对象进行访问,从而确保...

    iOS中的各种锁

    在实际开发中,选择合适的锁类型和使用策略对于提高应用性能和避免竞态条件至关重要。需要注意的是,过度使用锁可能会导致死锁和其他性能问题,因此在设计多线程代码时,应尽量减少锁的使用,并考虑其他并发控制机制...

Global site tag (gtag.js) - Google Analytics