java 内部锁_Java锁概念在内部如何工作?

小编典典

这些方法中最基本的是同步,它是使用监视器实现的。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 READYRUN 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 encode 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 // -----------------------------------------------------------------------------

2020-12-03

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值