精华内容
下载资源
问答
  • Java多线程锁释放

    千次阅读 2016-06-20 23:19:15
    Java多线程锁释放
    Java多线程运行环境中,在哪些情况下会使对象锁释放?


    由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的。在以下情况下,持有锁的线程会释放锁

    (1)执行完同步代码块,就会释放锁。(synchronized)
    (2)在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放。(exception)
    (3)在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进
    入对象的等待池。(wait)

    除了以上情况以外,只要持有锁的线程还没有执行完同步代码块,就不会释放锁。
    在下面情况下,线程是不会释放锁的
    (1)执行同步代码块的过程中,执行了Thread.sleep()方法,当前线程放弃CPU,开始睡眠,在睡眠中不会释放锁。
    (2)在执行同步代码块的过程中,执行了Thread.yield()方法,当前线程放弃CPU,但不会释放锁。
    (3)在执行同步代码块的过程中,其他线程执行了当前线程对象的suspend()方法,当前线程被暂停,但不会释放锁
    展开全文
  • 多线程锁的升级原理是什么?

    万次阅读 多人点赞 2019-05-20 11:04:06
    多线程锁的升级原理是什么? 锁的级别从低到高: 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 锁分级别原因: 没有优化以前,sychronized是重量级锁(悲观锁),使用 wait 和 notify、notifyAll 来切换...

    多线程锁的升级原理是什么?

    锁的级别从低到高:

    无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁

     

    锁分级别原因:

    没有优化以前,synchronized是重量级锁(悲观锁),使用 wait 和 notify、notifyAll 来切换线程状态非常消耗系统资源;线程的挂起和唤醒间隔很短暂,这样很浪费资源,影响性能。所以 JVM 对 synchronized 关键字进行了优化,把锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。

     

    无锁:没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功,其他修改失败的线程会不断重试直到修改成功。

     

    偏向锁:对象的代码一直被同一线程执行,不存在多个线程竞争,该线程在后续的执行中自动获取锁,降低获取锁带来的性能开销。偏向锁,指的就是偏向第一个加锁线程,该线程是不会主动释放偏向锁的,只有当其他线程尝试竞争偏向锁才会被释放。

    偏向锁的撤销,需要在某个时间点上没有字节码正在执行时,先暂停拥有偏向锁的线程,然后判断锁对象是否处于被锁定状态。如果线程不处于活动状态,则将对象头设置成无锁状态,并撤销偏向锁;

    如果线程处于活动状态,升级为轻量级锁的状态。

     

    轻量级锁:轻量级锁是指当锁是偏向锁的时候,被第二个线程 B 所访问,此时偏向锁就会升级为轻量级锁,线程 B 会通过自旋的形式尝试获取锁,线程不会阻塞,从而提高性能。

    当前只有一个等待线程,则该线程将通过自旋进行等待。但是当自旋超过一定的次数时,轻量级锁便会升级为重量级锁;当一个线程已持有锁,另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁。

     

    重量级锁:指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。

    重量级锁通过对象内部的监视器(monitor)实现,而其中 monitor 的本质是依赖于底层操作系统的 Mutex Lock 实现,操作系统实现线程之间的切换需要从用户态切换到内核态,切换成本非常高。

     

    锁状态对比:

     

    偏向锁

    轻量级锁

    重量级锁

    适用场景

    只有一个线程进入同步块

    虽然很多线程,但是没有冲突:多条线程进入同步块,但是线程进入时间错开因而并未争抢锁

    发生了锁争抢的情况:多条线程进入同步块并争用锁

    本质

    取消同步操作

    CAS操作代替互斥同步

    互斥同步

    优点

    不阻塞,执行效率高(只有第一次获取偏向锁时需要CAS操作,后面只是比对ThreadId)

    不会阻塞

    不会空耗CPU

    缺点

    适用场景太局限。若竞争产生,会有额外的偏向锁撤销的消耗

    长时间获取不到锁空耗CPU

    阻塞,上下文切换,重量级操作,消耗操作系统资源

     

    部分内容摘自:

    http://www.jetchen.cn/synchronized-status/

    https://www.liangzl.com/get-article-detail-17940.html

     


    【Java面试题与答案】整理推荐

     

    展开全文
  • Java提供了多种多线程锁机制的实现方式,常见的有: synchronized ReentrantLock Semaphore AtomicInteger等 每种机制都有优缺点与各自的适用场景,必须熟练掌握他们的特点才能在Java多线程应用开发时得心应手。...

    Java提供了多种多线程锁机制的实现方式,常见的有:

    1.  synchronized
    2.  ReentrantLock
    3.  Semaphore
    4.  AtomicInteger等

    每种机制都有优缺点与各自的适用场景,必须熟练掌握他们的特点才能在Java多线程应用开发时得心应手。

    4种Java线程锁(线程同步)

    高并发编程系列:4种常用Java线程锁的特点,性能比较、使用场景

    1.synchronized

    在Java中synchronized关键字被常用于维护数据一致性。

    synchronized机制是给共享资源上锁,只有拿到锁的线程才可以访问共享资源,这样就可以强制使得对共享资源的访问都是顺序的。

    Java开发人员都认识synchronized,使用它来实现多线程的同步操作是非常简单的,只要在需要同步的对方的方法、类或代码块中加入该关键字,它能够保证在同一个时刻最多只有一个线程执行同一个对象的同步代码,可保证修饰的代码在执行过程中不会被其他线程干扰。使用synchronized修饰的代码具有原子性和可见性,在需要进程同步的程序中使用的频率非常高,可以满足一般的进程同步要求。

    synchronized (obj) {

    //方法

    …….

    }

    synchronized实现的机理依赖于软件层面上的JVM,因此其性能会随着Java版本的不断升级而提高。

    到了Java1.6,synchronized进行了很多的优化,有适应自旋、锁消除、锁粗化、轻量级锁及偏向锁等,效率有了本质上的提高。在之后推出的Java1.7与1.8中,均对该关键字的实现机理做了优化。

    需要说明的是,当线程通过synchronized等待锁时是不能被Thread.interrupt()中断的,因此程序设计时必须检查确保合理,否则可能会造成线程死锁的尴尬境地。

    最后,尽管Java实现的锁机制有很多种,并且有些锁机制性能也比synchronized高,但还是强烈推荐在多线程应用程序中使用该关键字,因为实现方便,后续工作由JVM来完成,可靠性高。只有在确定锁机制是当前多线程程序的性能瓶颈时,才考虑使用其他机制,如ReentrantLock等。

    2.ReentrantLock

    可重入锁,顾名思义,这个锁可以被线程多次重复进入进行获取操作。

    ReentantLock继承接口Lock并实现了接口中定义的方法,除了能完成synchronized所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。

    Lock实现的机理依赖于特殊的CPU指定,可以认为不受JVM的约束,并可以通过其他语言平台来完成底层的实现。在并发量较小的多线程应用程序中,ReentrantLock与synchronized性能相差无几,但在高并发量的条件下,synchronized性能会迅速下降几十倍,而ReentrantLock的性能却能依然维持一个水准。

    因此我们建议在高并发量情况下使用ReentrantLock。

    ReentrantLock引入两个概念:公平锁与非公平锁

    公平锁指的是锁的分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁。反之,JVM按随机、就近原则分配锁的机制则称为不公平锁。

    ReentrantLock在构造函数中提供了是否公平锁的初始化方式,默认为非公平锁。这是因为,非公平锁实际执行的效率要远远超出公平锁,除非程序有特殊需要,否则最常用非公平锁的分配机制。

    ReentrantLock通过方法lock()与unlock()来进行加锁与解锁操作,与synchronized会被JVM自动解锁机制不同,ReentrantLock加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况,使用ReentrantLock必须在finally控制块中进行解锁操作。通常使用方式如下所示:

    Lock lock = new ReentrantLock();

    try {

    lock.lock();

    //…进行任务操作5 }

    finally {

    lock.unlock();

    }

    3.Semaphore

    上述两种锁机制类型都是“互斥锁”,学过操作系统的都知道,互斥是进程同步关系的一种特殊情况,相当于只存在一个临界资源,因此同时最多只能给一个线程提供服务。但是,在实际复杂的多线程应用程序中,可能存在多个临界资源,这时候我们可以借助Semaphore信号量来完成多个临界资源的访问。

    Semaphore基本能完成ReentrantLock的所有工作,使用方法也与之类似,通过acquire()与release()方法来获得和释放临界资源。

    经实测,Semaphone.acquire()方法默认为可响应中断锁,与ReentrantLock.lockInterruptibly()作用效果一致,也就是说在等待临界资源的过程中可以被Thread.interrupt()方法中断。

    此外,Semaphore也实现了可轮询的锁请求与定时锁的功能,除了方法名tryAcquire与tryLock不同,其使用方法与ReentrantLock几乎一致。Semaphore也提供了公平与非公平锁的机制,也可在构造函数中进行设定。

    Semaphore的锁释放操作也由手动进行,因此与ReentrantLock一样,为避免线程因抛出异常而无法正常释放锁的情况发生,释放锁的操作也必须在finally代码块中完成

    4.AtomicInteger

    首先说明,此处AtomicInteger是一系列相同类的代表之一,常见的还有AtomicLong、AtomicLong等,他们的实现原理相同,区别在与运算对象类型的不同。

    我们知道,在多线程程序中,诸如++i

    i++等运算不具有原子性,是不安全的线程操作之一。通常我们会使用synchronized将该操作变成一个原子操作,但JVM为此类操作特意提供了一些同步类,使得使用更方便,且使程序运行效率变得更高。通过相关资料显示,通常AtomicInteger的性能是ReentantLock的好几倍。

    Java线程锁总结

    1.synchronized:

    在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好。

    2.ReentrantLock:

    在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍,而ReentrantLock确还能维持常态。

    高并发量情况下使用ReentrantLock。

    3.Atomic:

    和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。

    所以,我们写同步的时候,优先考虑synchronized,如果有特殊需要,再进一步优化。ReentrantLock和Atomic如果用的不好,不仅不能提高性能,还可能带来灾难。

    以上就是Java线程锁的详解,除了从编程的角度应对高并发,更多还需要从架构设计的层面来应对高并发场景,例如:Redis缓存、CDN、异步消息等,详细的内容如下。

    原文链接:http://youzhixueyuan.com/4-kinds-of-java-thread-locks.html

    展开全文
  • C#多线程锁

    千次阅读 2017-04-18 19:33:43
    c#多线程操作队列

    C#开发中会常遇到多线程的问题,当多个线程同时对同一个资源进行操作时,就需要注意线程同步的问题。线程如果不同步,可能会造成与预计不同的结果,这时就要对资源进行上锁。当多个线程操作一个全局变量时,如果对全局变量进行上锁,则当一个线程访问这个全局变量时,另一个线程并不能去访问这个全局变量,只有等解锁资源后,其余线程才有机会去访问。这就保证了线程同步。下面是示例:
    两个线程fun1和fun2同时对队列进行入队操作,当入队数量比较小时,可能没有问题,当数量较大时,会发现队列中元素个数并不是两个线程入队元素的和。

       public class student
            {
                public int age;
                public string name;
                public int num;
            }
            Queue<student> q= new Queue<student>();
    
            public void fun1()
            {         
                Monitor.Enter(this);//锁定,保持同步
                student s = new student();
                for (int i = 0; i < 2000000; i++)
                {
                    s.num = 1;
                    s.age = i;
                    s.name = "A" + i.ToString();
                    q.Enqueue(s);
                }
                Monitor.Exit(this);//取消锁定
    
            }
    
            public void test_queue_nolock()
            {
                Thread t1= new Thread(new ThreadStart(fun1));
                t1.Name="线程1";
                t1.Start();
                Thread t2 = new Thread(new ThreadStart(fun1));
                t2.Name = "线程2";
                t2.Start();       
            }
    
            private void btn_test_Click(object sender, EventArgs e)
            {
                test_queue_nolock();
                timer_dequeue.Enabled = true;
            }
    
    
            private void timer_queue_Tick(object sender, EventArgs e)
            {
                Console.WriteLine("队列写入了{0}条数据", q.Count);
            }

    其中线程的启动为:
    1)不带参数的启动:Thread t1= new Thread(new ThreadStart(fun1));
    然后再 t1.start()开启该线程
    2)带参数的启动方法,就要使用ParameterizedThreadStart委托来实例化Thread了,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。ParameterizedThreadStart定义为:
    public delegate void ParameterizedThreadStart(object obj);
    Thread t1= new Thread(new ThreadStart(fun1));
    t1.start(100);此时的fun1应该有一个object 参数
    具体可参考:http://blog.csdn.net/zhoufoxcn/article/details/4402999

    展开全文
  • java多线程锁

    千次阅读 2012-05-11 14:56:56
    我们已经了解了Java多线程编程中常用的关键字synchronized,以及与之相关的对象机制。这一节中,让 我们一起来认识JDK 5中新引入的并发框架中的机制。 我想很多购买了《Java程序员面试宝典》之类图书的朋友...
  • Java多线程锁如何进行数据同步共享

    千次阅读 2011-10-10 15:37:49
    Java多线程锁是为了解决数据同步中的数据安全问题,下面我们就来详细的学习下有关于Java多线程锁的相关问题。只有不断的学习才能不断的提高自身的相关技术。 大多数应用程序要求线程互相通信来同步它们的动作。在...
  • java 多线程 降级

    千次阅读 2018-04-19 21:44:22
    如果当前线程拥有写,然后将其释放,最后再获取读,这种并不能称之为降级,降级指的是把持住(当前拥有的)写,再获取到读,随后释放(先前有用的)写的过程。下面给出一个降级的示例,当数据变动时,...
  • Java多线程锁对象的改变

    千次阅读 2016-11-22 15:33:01
    在将任何数据类型作为同步时,需要注意的是,是否有线程同时持有对象,如果同时持有相同的对象,则这些线程之间就是同步的;如果分别获得对象,这些线程之间就是异步的。 这个时候线程A和B持有的都是...
  • 详解Java多线程锁之synchronized

    千次阅读 2019-06-13 08:36:27
    轻量级(Lightweight Locking):在没有多线程竞争的情况下避免重量级互斥,只需要依靠一条CAS原子指令就可以完成的获取及释放。 在JDK1.6之后,synchronized不再是重量级的状态变成以下四种状态:...
  • 多线程锁使用的原则

    千次阅读 2017-01-12 15:22:56
    规则10.1 多线程、进程并行访问共享资源时,一定要加锁保护  说明:共享资源包括全局变量,静态变量,共享内存,文件等。 建议封装像智能指针一样的对象对锁进行管理,比如我们就封装了一个auto_lock,在构造时...
  • 详解Java多线程锁之Lock和ReadWriteLock

    千次阅读 2019-06-14 08:00:00
    ReentrantLock是实现了Lock接口的类,属于独享,独享在同一时刻仅有一个线程可以进行访问。Lock接口很简单,实现了如下: public interface Lock { void lock(); void lockInterruptibly() throws ...
  • linux多线程锁机制

    千次阅读 2013-03-25 19:18:26
    自旋(spinlock)和互斥体(mutex)是保护内核临界区的两种基本机制。 2.互斥:pthread_mutex,属于sleep-waiting类型的。互斥量是实现最简单的类型,因此有一些教科书一般以互斥量为例对锁原语进行描述。互斥量...
  • iOS 多线程 互斥 同步

    万次阅读 2013-02-04 14:49:52
    在iOS中有几种方法来解决多线程访问同一个内存地址的互斥同步问题: 方法一,@synchronized(id anObject),(最简单的方法) 会自动对参数对象加锁,保证临界区内的代码线程安全 @synchronized(self) { // 这段...
  • 多线程线程锁的使用

    千次阅读 2018-05-07 13:15:40
    多线程的程序编写中,常常遇到共享资源使用冲突解决的苦恼。终于看到并测试了一种简单方法。线程锁的5个要素:CRITICAL_SECTION g_cs; //定义线程锁InitializeCriticalSection(&amp;g_cs); //初始化...
  • python多线程,线程锁

    万次阅读 2019-01-19 23:39:10
    python使用多线程, 不一定运行速度快,这里引入GIL(global interpreter lock) python解释器中任意时刻都只有一个线程在执行; GIL执行过程: 1). 设置一个GIL; 2). 切换线程去准备执行任务(Runnale就绪状态)...
  • MFC多线程互斥的使用

    千次阅读 2019-10-04 23:14:12
    MFC多线程互斥的使用 本例演示在MFC中使用多线程。第一部分实现多线程的开启、暂停、继续、注销(见上一篇文章MFC多线程的开启、暂停、继续和注销)。第二部分实现两个线程互斥的使用。 演示系统为Win10,平台为...
  • C++多线程互斥

    千次阅读 2019-05-31 14:20:25
    在C++的多线程编程中,对一些需要互斥访问的临界区资源或者互斥运行的函数,需要通过互斥的方式来保证。标准库中提供了互斥 下面是一段简单的多线程代码 #include <iostream> #include <thread> ...
  • 文章目录多线程的升级原理是什么? 多线程的升级原理是什么?
  • 以后但凡标题中出现数字括号的,就表示为一个短篇系列(大概3~5篇博文的样子...理解二者的区别的联系才是关键:进程是一个执行中的程序(如打开任务管理器看到的系统进程),而线程的概念依托于进程,是在进程下执...
  • Android多线程研究(9)——线程锁Lock

    万次阅读 多人点赞 2014-06-08 21:08:55
    在前面我们在解决线程同步问题的时候使用了synchronized关键字,今天我们来看看Java 5.0以后提供的线程锁Lock.Lock接口的实现类提供了比使用synchronized关键字更加灵活和广泛的锁定对象操作,而且是以面向对象的...
  • 多线程方向的

    千次阅读 2018-06-21 23:39:25
    多线程方向的 注意: 环境说明: IDE: IntelliJ IDEA 2017 java version: jdk1.8 GitHub代码地址:https://github.com/1344115844/learning 简单 简单的给资源加把;以下的所有代码实现都使用同一个类...
  • JUC多线程:synchronized 机制原理

    千次阅读 多人点赞 2021-08-26 08:53:31
    synchronized 通过当前线程持有对象,从而拥有访问权限,而其他没有持有当前对象线程无法拥有访问权限,保证在同一时刻,只有一个线程可以执行某个方法或者某个代码块,从而保证线程安全。synchronized 机制...
  • ReentrantLock属于排他,这些在同一时刻只允许一个线程进行访问,而读写在同一时刻可以允许线程访问,但是在写线程访问时,所有的读和其他写线程都被阻塞。读写维护了一对,一个读和一个写,通过...
  • System.Threading.Thread.SpinWait System.Threading.SpinWait System.Threading.SpinLock
  • 快速理解线程锁

    万次阅读 2018-05-30 17:28:13
    多线程可以同时运行多个任务 但是当多个线程同时访问共享数据时,可能导致数据不同步,甚至错误! so,不使用线程锁, 可能导致错误 啰嗦两句: 比如你在银行取钱的同时你女朋友用支付宝取钱 ...
  • 在学习java多线程这一块知识的时候,遇到了很多个关于线程锁什么时候释放的问题,现总结几种释放锁和不释放锁的操作如下
  • Java 多线程全局与对象

    千次阅读 2018-05-12 17:49:04
      我们看一个例子: class Demo { public synchronized void test() { ...test方法开始执行,当前线程为:&quot;+Thread.currentThread().getName()); try { Thread.sleep(1000); ...
  • 多线程面试题和答案:线程锁+线程池+线程同步1、并发编程三要素?2、多线程的价值?3、创建线程的有哪些方式?区别是什么?4、创建线程的三种方式的对比?4、线程的生命周期及五种基本状态及转换条件1、Java线程具有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 585,656
精华内容 234,262
关键字:

多线程锁