栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Java锁概念在内部如何工作?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java锁概念在内部如何工作?

与往常一样,JLS提供了答案(17.1):

这些方法中最基本的是同步,它是使用监视器实现的。Java中的每个对象都与一个监视器关联,线程可以锁定或解锁监视器。一次只能有一个线程在监视器上保持锁。任何其他试图锁定该监视器的线程都将被阻止,直到它们可以在该监视器上获得锁定为止。线程t可以多次锁定特定的监视器。每次解锁都会逆转一次锁定操作的效果。

因此,不,

lock
它不像
Object
(仅通过查看Object的源代码即可看到)中的字段。相反,每个
Object
监视器都与一个“监视器”相关联,并且正是此监视器被锁定或解锁。

我只是想指出一个进一步的参考,其中详细介绍了“ Java的工作方式”,以确保它不会被忽略。这位于@selig在下面发现的C
++代码的注释中,我鼓励对下面内容的所有赞扬都可以得到他的回答。您可以在此处提供的链接中查看完整的源代码。

  126 // -----------------------------------------------------------------------------  127 // Theory of operations -- Monitors lists, thread residency, etc:  128 //  129 // * A thread acquires ownership of a monitor by successfully  130 //   CAS()ing the _owner field from null to non-null.  131 //  132 // * Invariant: A thread appears on at most one monitor list --  133 //   cxq, EntryList or WaitSet -- at any one time.  134 //  135 // * Contending threads "push" themselves onto the cxq with CAS  136 //   and then spin/park.  137 //  138 // * After a contending thread eventually acquires the lock it must  139 //   dequeue itself from either the EntryList or the cxq.  140 //  141 // * The exiting thread identifies and unparks an "heir presumptive"  142 //   tentative successor thread on the EntryList.  Critically, the  143 //   exiting thread doesn't unlink the successor thread from the EntryList.  144 //   After having been unparked, the wakee will recontend for ownership of  145 //   the monitor.   The successor (wakee) will either acquire the lock or  146 //   re-park itself.  147 //  148 //   Succession is provided for by a policy of competitive handoff.  149 //   The exiting thread does _not_ grant or pass ownership to the  150 //   successor thread.  (This is also referred to as "handoff" succession").  151 //   Instead the exiting thread releases ownership and possibly wakes  152 //   a successor, so the successor can (re)compete for ownership of the lock.  153 //   If the EntryList is empty but the cxq is populated the exiting  154 //   thread will drain the cxq into the EntryList.  It does so by  155 //   by detaching the cxq (installing null with CAS) and folding  156 //   the threads from the cxq into the EntryList.  The EntryList is  157 //   doubly linked, while the cxq is singly linked because of the  158 //   CAS-based "push" used to enqueue recently arrived threads (RATs).  159 //  160 // * Concurrency invariants:  161 //  162 //   -- only the monitor owner may access or mutate the EntryList.  163 //      The mutex property of the monitor itself protects the EntryList  164 //      from concurrent interference.  165 //   -- only the monitor owner may detach the cxq.  166 //  167 // * The monitor entry list operations avoid locks, but strictly speaking  168 //   they're not lock-free.  Enter is lock-free, exit is not.  169 //   See http://j2se.east/~dice/PERSIST/040825-LockFreeQueues.html  170 //  171 // * The cxq can have multiple concurrent "pushers" but only one concurrent  172 //   detaching thread.  This mechanism is immune from the ABA corruption.  173 //   More precisely, the CAS-based "push" onto cxq is ABA-oblivious.  174 //  175 // * Taken together, the cxq and the EntryList constitute or form a  176 //   single logical queue of threads stalled trying to acquire the lock.  177 //   We use two distinct lists to improve the odds of a constant-time  178 //   dequeue operation after acquisition (in the ::enter() epilog) and  179 //   to reduce heat on the list ends.  (c.f. Michael Scott's "2Q" algorithm).  180 //   A key desideratum is to minimize queue & monitor metadata manipulation  181 //   that occurs while holding the monitor lock -- that is, we want to  182 //   minimize monitor lock holds times.  Note that even a small amount of  183 //   fixed spinning will greatly reduce the # of enqueue-dequeue operations  184 //   on EntryList|cxq.  That is, spinning relieves contention on the "inner"  185 //   locks and monitor metadata.  186 //  187 //   Cxq points to the the set of Recently Arrived Threads attempting entry.  188 //   Because we push threads onto _cxq with CAS, the RATs must take the form of  189 //   a singly-linked LIFO.  We drain _cxq into EntryList  at unlock-time when  190 //   the unlocking thread notices that EntryList is null but _cxq is != null.  191 //  192 //   The EntryList is ordered by the prevailing queue discipline and  193 //   can be organized in any convenient fashion, such as a doubly-linked list or  194 //   a circular doubly-linked list.  Critically, we want insert and delete operations  195 //   to operate in constant-time.  If we need a priority queue then something akin  196 //   to Solaris' sleepq would work nicely.  Viz.,  197 //   http://agg.eng/ws/on10_nightly/source/usr/src/uts/common/os/sleepq.c.  198 //   Queue discipline is enforced at ::exit() time, when the unlocking thread  199 //   drains the cxq into the EntryList, and orders or reorders the threads on the  200 //   EntryList accordingly.  201 //  202 //   Barring "lock barging", this mechanism provides fair cyclic ordering,  203 //   somewhat similar to an elevator-scan.  204 //  205 // * The monitor synchronization subsystem avoids the use of native  206 //   synchronization primitives except for the narrow platform-specific  207 //   park-unpark abstraction.  See the comments in os_solaris.cpp regarding  208 //   the semantics of park-unpark.  Put another way, this monitor implementation  209 //   depends only on atomic operations and park-unpark.  The monitor subsystem  210 //   manages all RUNNING->BLOCKED and BLOCKED->READY transitions while the  211 //   underlying OS manages the READY<->RUN transitions.  212 //  213 // * Waiting threads reside on the WaitSet list -- wait() puts  214 //   the caller onto the WaitSet.  215 //  216 // * notify() or notifyAll() simply transfers threads from the WaitSet to  217 //   either the EntryList or cxq.  Subsequent exit() operations will  218 //   unpark the notifyee.  Unparking a notifee in notify() is inefficient -  219 //   it's likely the notifyee would simply impale itself on the lock held  220 //   by the notifier.  221 //  222 // * An interesting alternative is to enpre cxq as (List,LockByte) where  223 //   the LockByte is 0 iff the monitor is owned.  _owner is simply an auxiliary  224 //   variable, like _recursions, in the scheme.  The threads or Events that form  225 //   the list would have to be aligned in 256-byte addresses.  A thread would  226 //   try to acquire the lock or enqueue itself with CAS, but exiting threads  227 //   could use a 1-0 protocol and simply STB to set the LockByte to 0.  228 //   Note that is is *not* word-tearing, but it does presume that full-word  229 //   CAS operations are coherent with intermix with STB operations.  That's true  230 //   on most common processors.  231 //  232 // * See also http://blogs.sun.com/dave  233   234   235 // -----------------------------------------------------------------------------


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/393615.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号