java中多线程使用lock锁 其中一个使用unlock方法为什么锁就失效了 java 多线程在竞争一个内部锁时,只有一个线程获得锁,其它...

java Lock\u9501\u4e3a\u4ec0\u4e48\u4e0d\u76f4\u63a5\u4f7f\u7528

\u4e3b\u8981\u4e3a\u4e86\u591a\u7ebf\u7a0b\u8bbf\u95ee\u5171\u4eab\u8d44\u6e90\u65f6\uff0c\u4fdd\u8bc1\u53ea\u80fd\u6709\u4e00\u4e2a\u7ebf\u7a0b\u64cd\u4f5c\u8d44\u6e90\uff0c\u6bd4\u5982\u8bf4\u4e00\u4e2aservlet\u4e2d\u5bf9\u6839\u636e\u53c2\u6570 \u4e00\u4e2a\u516c\u5171\u53d8\u91cf\u8bbe\u7f6e\u503c \uff0c\u5982\u679c\u4e0d\u91c7\u7528lock\u90a3\u4e48\u5728\u5e76\u53d1\u8bbf\u95ee\u65f6\u5c31\u65e0\u6cd5\u4fdd\u8bc1\u6bcf\u4e2a\u7ebf\u7a0b\u4e2d\u516c\u5171\u53d8\u91cf\u8bbe\u7f6e\u7684\u503c\u90fd\u662f\u5404\u81ea\u7ebf\u7a0b\u7684\uff0c\u5728\u540e\u7eed\u7684\u5e94\u7528\u4e2d\u53d8\u91cf\u7684\u503c\u53ef\u80fd\u4f1a\u9519\u4e71\uff0c\u52a0\u4e86lock\u4e4b\u540e\u5c31\u4fdd\u8bc1\u4e86\u5728\u4e00\u4e2a\u7ebf\u7a0b\u4e2d\u4ece\u5934\u5230\u5c3e\u90fd\u662f\u4e00\u81f4\u7684

1. \u7a0b\u5e8f\u901a\u8fc7Thread t = new Thread()\uff0c\u8c03\u7528t.start()\u542f\u52a8\u4e00\u4e2a\u7ebf\u7a0b\uff0c\u4f7f\u8be5\u7ebf\u7a0b\u8fdb\u5165\u53ef\u8fd0\u884c(Runnable)\u7684\u72b6\u6001\u3002
2. \u7531JVM\u7684\u51b3\u5b9a\u53bb\u8c03\u5ea6(Scheduler) \u5728\u53ef\u8fd0\u884c\u72b6\u6001\uff08Runnable\uff09\u4e0b\u7684\u7ebf\u7a0b,\u4f7f\u8be5\u7ebf\u7a0b\u5904\u4e8e\u8fd0\u884c (Running) \u72b6\u6001,\u7531\u4e8eJVM\u7684\u8c03\u5ea6\u4f1a\u51fa\u73b0\u4e0d\u53ef\u63a7\u6027\uff0c\u5373\u4e0d\u662f\u4f18\u5148\u7ea7\u9ad8\u7684\u5148\u88ab\u8c03\u7528\uff0c\u53ef\u80fd\u5148\u8c03\u7528\uff0c\u4e5f\u53ef\u80fd\u540e\u8c03\u7528\u7684\u7684\u60c5\u51b5\u3002\u8fd0\u884c\u72b6\u6001(Running)\u4e0b\uff0c\u8c03\u7528\u793c\u8ba9yield()\u65b9\u6cd5\uff0c\u53ef\u4ee5\u4f7f\u7ebf\u7a0b\u56de\u5230\u53ef\u8fd0\u884c\u72b6\u6001(Runnable)\u4e0b\uff0c\u518d\u6b21JVM\u7684\u8c03\u5ea6\uff08\u5e76\u4e0d\u4f9d\u8d56\u4f18\u5148\u7ea7\uff09\u3002
3. \u7ebf\u7a0b\u5728Running\u7684\u8fc7\u7a0b\u4e2d\u53ef\u80fd\u4f1a\u9047\u5230\u963b\u585e(Blocked)\u60c5\u51b5
\u2460\uff0e\u8c03\u7528join()\u548csleep()\u65b9\u6cd5\uff0csleep()\u65f6\u95f4\u7ed3\u675f\u6216\u88ab\u6253\u65ad\uff0cjoin()\u4e2d\u65ad,IO\u5b8c\u6210\u90fd\u4f1a\u56de\u5230Runnable\u72b6\u6001\uff0c\u7b49\u5f85JVM\u7684\u8c03\u5ea6\u3002
\u2461\uff0e\u8c03\u7528wait()\uff0c\u4f7f\u8be5\u7ebf\u7a0b\u5904\u4e8e\u7b49\u5f85\u6c60(wait blocked pool),\u76f4\u5230notify()/notifyAll()\uff0c\u7ebf\u7a0b\u88ab\u5524\u9192\u88ab\u653e\u5230\u9501\u6c60(lock blocked pool )\uff0c\u91ca\u653e\u540c\u6b65\u9501\u4f7f\u7ebf\u7a0b\u56de\u5230\u53ef\u8fd0\u884c\u72b6\u6001\uff08Runnable\uff09
\u2462\uff0e\u5bf9Running\u72b6\u6001\u7684\u7ebf\u7a0b\u52a0\u540c\u6b65\u9501(Synchronized)\u4f7f\u5176\u8fdb\u5165(lock blocked pool ),\u540c\u6b65\u9501\u88ab\u91ca\u653e\u8fdb\u5165\u53ef\u8fd0\u884c\u72b6\u6001(Runnable)\u3002
4. \u7ebf\u7a0brun()\u8fd0\u884c\u7ed3\u675f\u6216\u5f02\u5e38\u9000\u51fa\uff0c\u7ebf\u7a0b\u5230\u8fbe\u6b7b\u4ea1\u72b6\u6001(Dead)
sleep\u548cwait\u7684\u533a\u522b\u6709\uff1a
1\uff0c\u7c7b\uff1a\u8fd9\u4e24\u4e2a\u65b9\u6cd5\u6765\u81ea\u4e0d\u540c\u7684\u7c7b\u5206\u522b\u662fThread\u548cObject
2\uff0c\u9501\uff1a\u6700\u4e3b\u8981\u662fsleep\u65b9\u6cd5\u6ca1\u6709\u91ca\u653e\u9501\uff0c\u800cwait\u65b9\u6cd5\u91ca\u653e\u4e86\u9501\uff0c\u4f7f\u5f97\u5176\u4ed6\u7ebf\u7a0b\u53ef\u4ee5\u4f7f\u7528\u540c\u6b65\u63a7\u5236\u5757\u6216\u8005\u65b9\u6cd5\u3002
3\uff0c\u57df\uff1await\uff0cnotify\u548cnotifyAll\u53ea\u80fd\u5728\u540c\u6b65\u63a7\u5236\u65b9\u6cd5\u6216\u8005\u540c\u6b65\u63a7\u5236\u5757\u91cc\u9762\u4f7f\u7528\uff0c\u800csleep\u53ef\u4ee5\u5728
\u4efb\u4f55\u5730\u65b9\u4f7f\u7528
synchronized(x){
x.notify()
//\u6216\u8005wait()
}
4\uff0c\u5f02\uff1asleep\u5fc5\u987b\u6355\u83b7\u5f02\u5e38\uff0c\u800cwait\uff0cnotify\u548cnotifyAll\u4e0d\u9700\u8981\u6355\u83b7\u5f02\u5e38
5\uff0c\u505c\uff1a\u5176\u5b9e\u4e24\u8005\u90fd\u53ef\u4ee5\u8ba9\u7ebf\u7a0b\u6682\u505c\u4e00\u6bb5\u65f6\u95f4,\u4f46\u662f\u672c\u8d28\u7684\u533a\u522b\u662f\u4e00\u4e2a\u7ebf\u7a0b\u7684\u8fd0\u884c\u72b6\u6001\u63a7\u5236,\u4e00\u4e2a\u662f\u7ebf\u7a0b\u4e4b\u95f4\u7684\u901a\u8baf\u7684\u95ee\u9898
notify():\u5524\u9192\u4e00\u4e2a\u5904\u4e8e\u7b49\u5f85\u72b6\u6001\u7684\u7ebf\u7a0b\uff0c\u6ce8\u610f\u7684\u662f\u5728\u8c03\u7528\u6b64\u65b9\u6cd5\u7684\u65f6\u5019\uff0c\u5e76\u4e0d\u80fd\u786e\u5207\u7684\u5524\u9192\u67d0\u4e00\u4e2a\u7b49\u5f85\u72b6\u6001\u7684\u7ebf\u7a0b\uff0c\u800c\u662f\u7531JVM\u786e\u5b9a\u5524\u9192\u54ea\u4e2a\u7ebf\u7a0b\uff0c\u800c\u4e14\u4e0d\u662f\u6309\u4f18\u5148\u7ea7\u3002
notifyAll():\u5524\u9192\u6240\u6709\u5904\u5165\u7b49\u5f85\u72b6\u6001\u7684\u7ebf\u7a0b\uff0c\u6ce8\u610f\u5e76\u4e0d\u662f\u7ed9\u6240\u6709\u5524\u9192\u7ebf\u7a0b\u4e00\u4e2a\u5bf9\u8c61\u7684\u9501\uff0c\u800c\u662f\u8ba9\u5b83\u4eec\u7ade\u4e89\u3002

Java中Lock,tryLock,lockInterruptibly的区别如下:
一、 lock()方法
使用lock()获取锁,若获取成功,标记下是该线程获取到了锁(用于锁重入),然后返回。若获取失败,这时跑一个for循环,循环中先将线程阻塞放入等待队列,当被调用signal()时线程被唤醒,这时进行锁竞争(因为默认使用的是非公平锁),如果此时用CAS获取到了锁那么就返回,如果没获取到那么再次放入等待队列,等待唤醒,如此循环。其间就算外部调用了interrupt(),循环也会继续走下去。一直到当前线程获取到了这个锁,此时才处理interrupt标志,若有,则执行 Thread.currentThread().interrupt(),结果如何取决于外层的处理。lock()最终执行的方法如下:

[java] view plain copy
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) { //如果竞争得到了锁
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted; //获取成功返回interrupted标志
}
// 只修改标志位,不做其他处理
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
其中parkAndCheckInterrupt()调用了LockSupport.park(),该方法使用Unsafe类将进程阻塞并放入等待队列,等待唤醒,和await()有点类似。

可以看到循环中检测到了interrupt标记,但是仅做 interrupted = true 操作,直到获取到了锁,才return interrupted,然后处理如下

[java] view plain copy
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt(); // 执行Thread.currentThread().interrupt()
}

二、 lockInterruptibly()方法
和lock()相比,lockInterruptibly()只有略微的修改,for循环过程中,如果检测到interrupt标志为true,则立刻抛出InterruptedException异常,这时程序变通过异常直接返回到最外层了,又外层继续处理,因此使用lockInterruptibly()时必须捕捉异常。lockInterruptibly()最终执行的方法如下:

[java] view plain copy
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return; //获取成功返回
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException(); //直接抛出异常
}
} finally {
if (failed)
cancelAcquire(node);
}
}

三、 tryLock()方法
使用tryLock()尝试获取锁,若获取成功,标记下是该线程获取到了锁,然后返回true;若获取失败,此时直接返回false,告诉外层没有获取到锁,之后的操作取决于外层,代码如下:

[java] view plain copy
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}



  • 绾跨▼闂村悓姝鐨鍑犵鏂规硶
    绛旓細浣跨敤閿侊紙Lock锛夛細閿佹槸涓绉嶅悓姝ユ満鍒讹紝鐢ㄤ簬纭繚鍦ㄥ绾跨▼鐜涓彧鏈変竴涓嚎绋嬪彲浠ヨ闂叡浜祫婧銆侸ava涓殑synchronized鍏抽敭瀛楀氨鏄熀浜庨攣鐨勫悓姝ユ満鍒躲備娇鐢ㄤ俊鍙烽噺锛圫emaphore锛夛細淇″彿閲忔槸涓绉嶇敤浜庢帶鍒跺苟鍙戣闂殑鍚屾鏈哄埗锛屽畠鍏佽鏈夐檺鏁伴噺鐨勭嚎绋嬪悓鏃惰闂叡浜祫婧愩侸ava涓殑Semaphore绫诲彲浠ョ敤鏉ュ疄鐜颁俊鍙烽噺銆備娇鐢ㄦ潯浠跺彉閲忥紙C...
  • Java澶氱嚎绋缂栫▼涓璴ock.lock()鏄粈涔堟剰鎬,鍦ㄧ嚎绛
    绛旓細绾跨▼閿侊紝绗竴涓猯ock鏄竴涓璞ock鎺ュ彛鐨勫疄渚嬪璞锛屽悗闈ock(),鏄柟娉曪紝琛ㄧずLock瀵硅薄鎵ц浜嗛攣瀹氭搷浣滐紝鍏朵粬鐨勭嚎绋嬮兘蹇呴』绛夎繖涓嚎绋嬪畬鎴愶紝骞堕噴鏀鹃攣涔嬪悗锛屾墠鑳芥墽琛岃閿佷綇鐨勪唬鐮佸潡
  • java涓绾跨▼浣跨敤lock閿 鍏朵腑涓涓娇鐢╱nlock鏂规硶涓轰粈涔堥攣灏卞け鏁堜簡
    绛旓細Java涓Lock锛宼ryLock锛宭ockInterruptibly鐨勫尯鍒涓嬶細涓銆 lock()鏂规硶浣跨敤lock()鑾峰彇閿侊紝鑻ヨ幏鍙栨垚鍔燂紝鏍囪涓嬫槸璇绾跨▼鑾峰彇鍒颁簡閿侊紙鐢ㄤ簬閿侀噸鍏ワ級锛岀劧鍚庤繑鍥炪傝嫢鑾峰彇澶辫触锛岃繖鏃惰窇涓涓猣or寰幆锛屽惊鐜腑鍏堝皢绾跨▼闃诲鏀惧叆绛夊緟闃熷垪锛屽綋琚皟鐢╯ignal()鏃剁嚎绋嬭鍞ら啋锛岃繖鏃惰繘琛岄攣绔炰簤锛堝洜涓洪粯璁や娇鐢ㄧ殑鏄潪鍏钩閿侊級锛...
  • 娣卞叆鐮旂┒ Java Synchronize 鍜 Lock 鐨鍖哄埆涓鐢ㄦ硶
    绛旓細lock锛氶渶瑕佹樉绀烘寚瀹氳捣濮嬩綅缃拰缁堟浣嶇疆銆備竴鑸娇鐢≧eentrantLock绫诲仛涓洪攣锛屽涓嚎绋嬩腑蹇呴』瑕佷娇鐢ㄤ竴涓猂eentrantLock绫诲仛涓哄璞℃墠鑳戒繚璇侀攣鐨勭敓鏁堛備笖鍦ㄥ姞閿佸拰瑙i攣澶勯渶瑕侀氳繃lock()鍜寀nlock()鏄剧ず鎸囧嚭銆傛墍浠ヤ竴鑸細鍦╢inally鍧椾腑鍐檜nlock()浠ラ槻姝婚攣銆傜敤娉曞尯鍒瘮杈冪畝鍗曪紝杩欓噷涓嶈禈杩颁簡锛屽鏋滀笉鎳傜殑鍙互鐪嬬湅Java鍩烘湰璇...
  • 娣卞叆鐮旂┒ Java Synchronize 鍜 Lock 鐨鍖哄埆涓鐢ㄦ硶
    绛旓細synchronized锛氬湪闇瑕佸悓姝ョ殑瀵硅薄涓姞鍏ユ鎺у埗锛宻ynchronized鍙互鍔犲湪鏂规硶涓婏紝涔熷彲浠ュ姞鍦ㄧ壒瀹氫唬鐮佸潡涓紝鎷彿涓〃绀洪渶瑕侀攣鐨勫璞°俵ock锛闇瑕佹樉绀烘寚瀹氳捣濮嬩綅缃拰缁堟浣嶇疆銆備竴鑸娇鐢≧eentrantLock绫诲仛涓洪攣锛屽涓嚎绋嬩腑蹇呴』瑕佷娇鐢ㄤ竴涓猂eentrantLock绫诲仛涓哄璞℃墠鑳戒繚璇侀攣鐨勭敓鏁堛備笖鍦ㄥ姞閿佸拰瑙i攣澶勯渶瑕侀氳繃lock()鍜寀nlock...
  • javalock浼氬悓姝ユ暟鎹箞
    绛旓細浼氥傚浜庡悓涓浠芥暟鎹紝濡傛灉涓涓嚎绋嬭鏁版嵁锛屽彟涓涓嚎绋嬪湪鍐欐暟鎹紝閭d箞璇诲埌鐨勬暟鎹笌鏈缁堢殑鏁版嵁鍙兘涓嶄竴鑷淬傚湪瀹為檯鐨勪笟鍔″満鏅腑锛岃鎿嶄綔杩滆繙澶т簬鍐欐搷浣溿傚湪java澶氱嚎绋鐜涓紝lock鍜屽悓姝ユ槸鎴戜滑涓瀹氫細浣跨敤鍒扮殑鍔熻兘銆
  • 鍏充簬synchronized鍜lock鍝簺璇存硶姝g‘
    绛旓細浠ヤ笅鏄synchronized鍜Lock鐨鍑犵甯歌璇存硶鐨勬纭у垎鏋愶細1. synchronized鏄Java涓鐨勫唴缃攣鏈哄埗锛氳繖鏄纭殑銆俿ynchronized鏄疛ava璇█涓殑涓涓叧閿瓧锛屽畠鐢ㄤ簬瀹炵幇鍚屾锛屽嵆纭繚鍚屼竴鏃跺埢鍙湁涓涓绾跨▼鍙互璁块棶琚玸ynchronized淇グ鐨勬柟娉曟垨浠g爜鍧椼傚綋涓涓嚎绋嬭繘鍏ヨsynchronized淇グ鐨勬柟娉曟垨浠g爜鍧楁椂锛屽畠浼氳幏鍙栬閿侊紝褰...
  • java 绋嬪簭涓庝箞淇濊瘉澶氱嚎绋嬬殑杩愯瀹夊叏?
    绛旓細2.2.1.浜掓枼閿 浜掓枼閿佸彧鏄竴涓攣姒傚康锛屽湪鍏朵粬鍦烘櫙涔熷彨鍋氱嫭鍗犻攣銆佹偛瑙傞攣绛夛紝鍏跺疄灏辨槸涓涓剰鎬濄傚畠鏄寚绾跨▼涔嬮棿鏄簰鏂ョ殑锛屾煇涓涓嚎绋嬭幏鍙栦簡鏌愪釜璧勬簮鐨勯攣锛岄偅涔堝叾浠栫嚎绋嬪氨鍙兘鐫$湢绛夊緟銆傚湪 Java 涓浜掓枼閿佺殑瀹炵幇涓鑸彨鍋氬悓姝绾跨▼閿锛屽叧閿瓧 synchronized锛屽畠閿佷綇鐨勮寖鍥存槸瀹冧慨楗扮殑浣滅敤鍩燂紝閿佷綇鐨勫璞℃槸锛...
  • java濡備綍瀹炵幇绾跨▼瀹夊叏,synchronized鍜lock鐨鍖哄埆,鍙噸鍏ラ攣
    绛旓細synchronized锛氬湪闇瑕佸悓姝ョ殑瀵硅薄涓姞鍏ユ鎺у埗锛宻ynchronized鍦ㄦ柟娉曚笂锛屼篃鍦ㄧ壒瀹氫唬鐮佸潡涓紝鎷彿涓〃绀洪渶瑕侀攣鐨勫璞°俵ock锛闇瑕佹樉绀烘寚瀹氳捣濮嬩綅缃拰缁堟浣嶇疆銆備竴鑸娇鐢≧eentrantLock绫诲仛涓洪攣锛屽涓嚎绋嬩腑蹇呴』瑕佷娇鐢ㄤ竴涓猂eentrantLock绫诲仛涓哄璞℃墠鑳戒繚璇侀攣鐨勭敓鏁堛備笖鍦ㄥ姞閿佸拰瑙i攣澶勯渶瑕侀氳繃lock()鍜寀nlock()鏄剧ず鎸囧嚭銆
  • 扩展阅读:java线程池配置参数 ... java lock接口 ... java python ... java多线程面试题及答案 ... volatile java ... mysql ... javascript入门 ... java设置线程 blocked ... spring cloud ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网