欢迎来到皮皮网网首页

【flac编码源码】【xscript 源码】【天鹅源码】synchronize源码

来源:品有影院源码 时间:2024-12-28 17:59:47

1.Linux 内核 rcu(顺序) 锁实现原理与源码解析
2.HashMap和Hashtable的区别
3.synchronize底层原理
4.Lock的await/singal 和 Object的wait/notify 的区别

synchronize源码

Linux 内核 rcu(顺序) 锁实现原理与源码解析

       结论是,Linux 内核中的 RCU(Read-Copy-Update)锁提供了一种无需阻塞的锁机制,旨在提高并发性能。传统的锁如自旋锁和互斥锁存在阻塞问题,而RCU锁通过读写分离、延迟删除策略来实现无锁或低阻塞的flac编码源码操作。

       RCU锁的核心原理是利用读写分离的策略。当有读任务 M 阅读链表时,写任务 N 可以在读任务完成后再进行修改,通过rcu_assign_pointer 修改指针,保留旧节点直到读任务结束。写任务通过synchronize_kernel等待所有读任务完成,而读任务则通过rcu_read_lock获取读锁,rcu_read_unlock释放,rcu_dereference访问数据。

       这种机制类似于垃圾回收机制,写者在操作后保留旧引用,xscript 源码直到所有读任务结束才删除。rcu_read_lock会禁止抢占,形成一个宽限期,确保读任务在读锁保护下完成,从而避免数据不一致。

       总的来说,RCU锁通过巧妙的策略,实现了低阻塞的天鹅源码并发控制,提高系统性能,而源码中的关键操作包括rcu_assign_pointer进行指针更新,synchronize_kernel等待读任务完成,以及读任务通过rcu_read_lock等函数进行锁的管理和数据访问。

HashMap和Hashtable的区别

       HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题。HashMap的工作原理、ArrayList与Vector的比较以及这个问题是有关Java 集合框架的最经典的问题。Hashtable是个过时的集合类,存在于Java API中很久了。在Java 4中被重写了,实现了Map接口,所以自此以后也成了Java集合框架中的一部分。Hashtable和HashMap在Java面试中相当容易被问到,甚至成为了集合框架面试题中最常被考的问题,所以在参加任何Java面试之前,都不要忘了准备这一题。

        这篇文章中,我们不仅将会看到HashMap和Hashtable的区别,还将看到它们之间的相似之处。

        HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。

        由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

        HashMap不能保证随着时间的推移Map中的元素次序是不变的。

        fail-fast机制在遍历一个集合时,当集合结构被修改,会抛出Concurrent Modification Exception。

        fail-fast会在以下两种情况下抛出ConcurrentModificationException

        集合被创建后,在遍历它的过程中修改了结构。

        注意 remove()方法会让expectModcount和modcount 相等,所以是不会抛出这个异常。

        当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改。

        迭代器在遍历过程中是直接访问内部数据的,因此内部的数据在遍历的过程中无法被修改。为了保证不被修改,迭代器内部维护了一个标记 “mode” ,当集合结构改变(添加删除或者修改),标记"mode"会被修改,而迭代器每次的hasNext()和next()方法都会检查该"mode"是否被改变,当检测到被修改时,抛出Concurrent Modification Exception。

        下面看看ArrayList迭代器部分的源码。

        可以看到它的标记“mode”为 expectedModeCount。

        fail-safe任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出ConcurrentModificationException。

        fail-safe机制有两个问题

        HashMap可以通过下面的语句进行同步:

        Map m = Collections.synchronizeMap(hashMap);

        Hashtable和HashMap有几个主要的不同:线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧。

synchronize底层原理

       synchronize底层原理是什么?我们先通过反编译下面的代码来看看Synchronized是如何实现对代码块进行同步的:

       1 package com.paddx.test.concurrent;

       2

       3 public class SynchronizedDemo {

       4 public void method() {

       5 synchronized (this) {

       6 System.out.println(Method 1 start);

       7 }

       8 }

       9 }

       反编译结果:

       关于这两条指令的作用,我们直接参考JVM规范中描述:

       monitorenter :

       Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:

        If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.

        If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.

        If another thread already owns the monitor associated with objectref, the thread blocks until the monitors entry count is zero, then tries again to gain ownership.

       这段话的大概意思为:

       每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的ipmana源码所有权,过程:

       1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。

       2、如果线程已经占有该monitor,只是10101101源码重新进入,则进入monitor的进入数加1.

       3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。

       monitorexit:

       The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.

       The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.

       这段话的大概意思为:

       执行monitorexit的线程必须是objectref所对应的monitor的所有者。

       指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。

       通过这两段描述,我们应该能很清楚的看出Synchronized的实现原理,Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。

       我们再来看一下同步方法的反编译结果:

       源代码:

       1 package com.paddx.test.concurrent;

       2

       3 public class SynchronizedMethod {

       4 public synchronized void method() {

       5 System.out.println(Hello World!);

       6 }

       7 }

       反编译结果:

       从反编译的结果来看,方法的同步并没有通过指令monitorenter和monitorexit来完成(理论上其实也可以通过这两条指令来实现),不过相对于普通方法,其常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的:当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。 其实本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。

Lock的await/singal 和 Object的wait/notify 的区别

       Lock的await/singal 和 Object的wait/notify 的区别

       åœ¨ä½¿ç”¨Lock之前,我们都使用Object 的wait和notify实现同步的。举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒。

       çº¿ç¨‹consumer 线程producer

        synchronize(obj){

        obj.wait();//没东西了,等待

       } synchronize(obj){

        obj.notify();//有东西了,唤醒

       }

       æœ‰äº†lock后,世道变了,现在是:

       lock.lock();

       condition.await();

       lock.unlock(); lock.lock();

       condition.signal();

       lock.unlock();

       ä¸ºäº†çªå‡ºåŒºåˆ«ï¼Œçœç•¥äº†è‹¥å¹²ç»†èŠ‚。区别有三点:

       1. lock不再用synchronize把同步代码包装起来;

       2. 阻塞需要另外一个对象condition;

       3. 同步和唤醒的对象是condition而不是lock,对应的方法是await和signal,而不是wait和notify。

       ä¸º

       ä»€ä¹ˆéœ€è¦ä½¿ç”¨condition呢?简单一句话,lock更灵活。以前的方式只能有一个等待队列,在实际应用时可能需要多个,比如读和写。为了这个灵活

       æ€§ï¼Œlock将同步互斥控制和等待队列分离开来,互斥保证在某个时刻只有一个线程访问临界区(lock自己完成),等待队列负责保存被阻塞的线程

       ï¼ˆcondition完成)。

       é€šè¿‡æŸ¥çœ‹ReentrantLock的源代码发现,condition其实是等待队列的一个管理者,condition确保阻塞的对象按顺序被唤醒。

       åœ¨Lock的实现中,LockSupport被用来实现线程状态的改变,后续将更进一步研究LockSupport的实现机制。