1 5 package com.tc.util.concurrent.locks; 6 7 import com.tc.exception.TCNotSupportedMethodException; 8 import com.tc.exception.TCRuntimeException; 9 import com.tc.object.bytecode.ManagerUtil; 10 import com.tc.object.lockmanager.api.LockLevel; 11 import com.tc.util.Stack; 12 import com.tc.util.UnsafeUtil; 13 14 import java.util.ArrayList ; 15 import java.util.Collection ; 16 import java.util.Date ; 17 import java.util.HashMap ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.concurrent.TimeUnit ; 21 import java.util.concurrent.locks.AbstractQueuedSynchronizer ; 22 import java.util.concurrent.locks.Condition ; 23 import java.util.concurrent.locks.Lock ; 24 25 public class ReentrantLock implements Lock , java.io.Serializable { 26 private boolean isFair; 27 28 29 transient Thread owner = null; 30 transient int numOfHolds = 0; 31 transient List waitingQueue = new ArrayList (); 32 transient int state = 0; 33 transient int numQueued = 0; 34 transient Stack lockInUnShared = new Stack(); 35 36 transient Object lock = new Object (); 37 38 public ReentrantLock() { 39 this.isFair = false; 40 41 initialize(); 42 } 43 44 public ReentrantLock(boolean fair) { 45 this.isFair = fair; 46 47 initialize(); 48 } 49 50 private void initialize() { 51 this.owner = null; 52 this.numOfHolds = 0; 53 this.waitingQueue = new ArrayList (); 54 this.state = 0; 55 this.numQueued = 0; 56 this.lock = new Object (); 57 this.lockInUnShared = new Stack(); 58 } 59 60 public void lock() { 61 Thread currentThread = Thread.currentThread(); 62 synchronized (lock) { 63 while (owner != null && owner != currentThread && lockInUnShared.contains(Boolean.TRUE)) { 64 try { 65 lock.wait(); 66 } catch (InterruptedException e) { 67 throw new TCRuntimeException(e); 68 } 69 } 70 71 waitingQueue.add(currentThread); 72 numQueued++; 73 } 74 75 ManagerUtil.monitorEnter(this, LockLevel.WRITE); 76 UnsafeUtil.monitorEnter(this); 77 78 synchronized (lock) { 79 innerSetLockState(); 80 waitingQueue.remove(currentThread); 81 numQueued--; 82 } 83 } 84 85 public void lockInterruptibly() throws InterruptedException { 86 if (Thread.interrupted()) throw new InterruptedException (); 87 lock(); 88 if (Thread.interrupted()) { 89 if (isHeldByCurrentThread()) { 90 unlock(); 91 } 92 throw new InterruptedException (); 93 } 94 } 95 96 public boolean tryLock() { 97 boolean canLock = false; 98 synchronized (lock) { 99 canLock = canProceedToLock(); 100 if (ManagerUtil.isManaged(this) && canLock) { 101 canLock = ManagerUtil.tryMonitorEnter(this, LockLevel.WRITE); 102 if (canLock) { 103 UnsafeUtil.monitorEnter(this); 104 } 105 } else { 106 if (canLock) { 107 UnsafeUtil.monitorEnter(this); 108 } 109 } 110 if (canLock) { 111 innerSetLockState(); 112 } 113 return canLock; 114 } 115 } 116 117 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { 118 if (!tryLock()) { 119 Thread currentThread = Thread.currentThread(); 120 121 long timeoutInNanos = TimeUnit.NANOSECONDS.convert(50, TimeUnit.MILLISECONDS); 122 long totalTimeoutInNanos = unit.toNanos(timeout); 123 124 if (timeoutInNanos > totalTimeoutInNanos) { 125 timeoutInNanos = totalTimeoutInNanos; 126 } 127 128 synchronized (lock) { 129 boolean locked = false; 130 131 while (!locked && totalTimeoutInNanos > 0) { 132 waitingQueue.add(currentThread); 133 numQueued++; 134 135 TimeUnit.NANOSECONDS.timedWait(lock, timeoutInNanos); 136 totalTimeoutInNanos -= timeoutInNanos; 137 138 waitingQueue.remove(currentThread); 139 numQueued--; 140 141 locked = tryLock(); 142 } 143 return locked; 144 } 145 } 146 return true; 147 } 148 149 public void unlock() { 150 boolean needDSOUnlock = false; 151 synchronized (lock) { 152 boolean isLockedInUnSharedMode = ((Boolean ) this.lockInUnShared.pop()).booleanValue(); 153 needDSOUnlock = !isLockedInUnSharedMode && ManagerUtil.isManaged(this) && !ManagerUtil.isCreationInProgress(); 154 155 if (--numOfHolds == 0) { 156 owner = null; 157 setState(0); 158 this.lockInUnShared.remove(Thread.currentThread()); 159 } 160 UnsafeUtil.monitorExit(this); 161 if (needDSOUnlock) { 162 ManagerUtil.monitorExit(this); 163 } else { 164 lock.notifyAll(); 165 } 166 } 167 } 168 169 public Condition newCondition() { 170 return new ConditionObject(new SyncCondition(), this); 171 } 172 173 public int getHoldCount() { 174 return (owner == Thread.currentThread()) ? numOfHolds : 0; 175 } 176 177 public boolean isHeldByCurrentThread() { 178 Thread owner = null; 179 int state = 0; 180 synchronized (lock) { 181 owner = this.owner; 182 state = getState(); 183 } 184 return state != 0 && owner == Thread.currentThread(); 185 } 186 187 public boolean isLocked() { 188 if (ManagerUtil.isManaged(this)) { 189 return isHeldByCurrentThread() || ManagerUtil.isLocked(this); 190 } else { 191 return getState() > 0; 192 } 193 } 194 195 public final boolean isFair() { 196 return isFair; 197 } 198 199 protected Thread getOwner() { 200 if (ManagerUtil.isManaged(this)) { 201 throw new TCNotSupportedMethodException(); 202 } else { 203 return (numOfHolds == 0) ? null : owner; 204 } 205 } 206 207 public final boolean hasQueuedThreads() { 208 if (ManagerUtil.isManaged(this)) { 209 return ManagerUtil.queueLength(this) > 0; 210 } else { 211 return numQueued > 0; 212 } 213 } 214 215 public final boolean hasQueuedThread(Thread thread) { 216 if (ManagerUtil.isManaged(this)) { 217 throw new TCNotSupportedMethodException(); 218 } else { 219 List waitingThreads = null; 220 synchronized (lock) { 221 waitingThreads = waitingQueue; 222 } 223 return waitingThreads.contains(thread); 224 } 225 } 226 227 public final int getQueueLength() { 228 if (ManagerUtil.isManaged(this)) { 229 return ManagerUtil.queueLength(this); 230 } else { 231 return numQueued; 232 } 233 } 234 235 protected Collection getQueuedThreads() { 236 if (ManagerUtil.isManaged(this)) { 237 throw new TCNotSupportedMethodException(); 238 } else { 239 List waitingThreads = null; 240 synchronized (lock) { 241 waitingThreads = waitingQueue; 242 } 243 return waitingThreads; 244 } 245 } 246 247 public boolean hasWaiters(Condition condition) { 248 if (condition == null) throw new NullPointerException (); 249 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject )) throw new IllegalArgumentException ( 250 "not owner"); 251 return false; 252 } 253 254 public int getWaitQueueLength(Condition condition) { 255 if (condition == null) throw new NullPointerException (); 256 if (!(condition instanceof ConditionObject)) throw new IllegalArgumentException ("not owner"); 257 return ((ConditionObject) condition).getWaitQueueLength(this); 258 } 259 260 protected Collection getWaitingThreads(Condition condition) { 261 if (ManagerUtil.isManaged(this)) throw new TCNotSupportedMethodException(); 262 263 if (condition == null) throw new NullPointerException (); 264 if (!(condition instanceof ConditionObject)) throw new IllegalArgumentException ("not owner"); 265 return ((ConditionObject) condition).getWaitingThreads(this); 266 } 267 268 private String getLockState() { 269 return (isLocked() ? (isHeldByCurrentThread() ? "[Locally locked]" : "[Remotelly locked]") : "[Unlocked]"); 270 } 271 272 public String toString() { 273 Thread owner = null; 274 return ManagerUtil.isManaged(this) ? (new StringBuilder ()).append(super.toString()).append(getLockState()) 275 .toString() : (new StringBuilder ()).append(super.toString()) 276 .append( 277 (owner = getOwner()) != null ? (new StringBuilder ()).append("[Locked by thread ") 278 .append(owner.getName()).append("]").toString() : "[Unlocked]").toString(); 279 280 } 281 282 private boolean canProceedToLock() { 283 boolean canLock = waitingQueue.isEmpty() && (getState() == 0); 284 return (owner == null && canLock) || (owner == Thread.currentThread()); 285 } 286 287 private void innerSetLockState() { 288 if (!ManagerUtil.isManaged(ReentrantLock.this) 289 || !ManagerUtil.isHeldByCurrentThread(ReentrantLock.this, LockLevel.WRITE)) { 290 this.lockInUnShared.push(Boolean.TRUE); 291 } else { 292 this.lockInUnShared.push(Boolean.FALSE); 293 } 294 295 owner = Thread.currentThread(); 296 numOfHolds++; 297 setState(1); 298 } 299 300 private void setState(int state) { 301 this.state = state; 302 } 303 304 private int getState() { 305 return this.state; 306 } 307 308 private void readObject(java.io.ObjectInputStream s) throws java.io.IOException , ClassNotFoundException { 309 s.defaultReadObject(); 310 isFair = s.readBoolean(); 311 initialize(); 312 } 313 314 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { 315 s.defaultWriteObject(); 316 s.writeBoolean(isFair); 317 } 318 319 private static class SyncCondition implements java.io.Serializable { 320 public SyncCondition() { 321 super(); 322 } 323 } 324 325 private static class ConditionObject implements Condition , java.io.Serializable { 326 private static final int SIGNALLED = 1; 327 private static final int NOT_SIGNALLED = 0; 328 329 private transient List waitingThreads; 330 private transient int numOfWaitingThreards; 331 private transient Map waitOnUnshared; 332 333 private final ReentrantLock originalLock; 334 private final Object realCondition; 335 private int signal = NOT_SIGNALLED; 336 337 private static long getSystemNanos() { 338 return System.nanoTime(); 339 } 340 341 public ConditionObject(Object realCondition, ReentrantLock originalLock) { 342 this.originalLock = originalLock; 343 this.realCondition = realCondition; 344 this.waitingThreads = new ArrayList (); 345 this.numOfWaitingThreards = 0; 346 this.waitOnUnshared = new HashMap (); 347 } 348 349 public ConditionObject() { 350 this.originalLock = null; 351 this.realCondition = null; 352 this.waitingThreads = new ArrayList (); 353 this.numOfWaitingThreards = 0; 354 this.waitOnUnshared = new HashMap (); 355 } 356 357 private void fullRelease() { 358 if (originalLock.getHoldCount() > 0) { 359 while (originalLock.getHoldCount() > 0) { 360 originalLock.unlock(); 361 } 362 } else { 363 while (Thread.holdsLock(originalLock)) { 366 UnsafeUtil.monitorExit(originalLock); 367 } 368 } 369 } 370 371 private void reacquireLock(int numOfHolds) { 372 if (originalLock.getHoldCount() >= numOfHolds) { return; } 373 while (originalLock.getHoldCount() < numOfHolds) { 374 originalLock.lock(); 375 } 376 } 377 378 private void checkCauseAndThrowInterruptedExceptionIfNecessary(TCRuntimeException e) throws InterruptedException { 379 if (e.getCause() instanceof InterruptedException ) { 380 throw (InterruptedException ) e.getCause(); 381 } else { 382 throw e; 383 } 384 } 385 386 private void checkCauseAndIgnoreInterruptedException(TCRuntimeException e) { 387 if (!(e.getCause() instanceof InterruptedException )) { throw e; } 388 } 389 390 private void addWaitOnUnshared() { 391 waitOnUnshared.put(Thread.currentThread(), ManagerUtil.isManaged(realCondition) ? Boolean.FALSE : Boolean.TRUE); 392 } 393 394 private boolean isLockRealConditionInUnshared() { 395 if (!ManagerUtil.isManaged(realCondition) || !ManagerUtil.isHeldByCurrentThread(realCondition, LockLevel.WRITE)) { return true; } 396 return false; 397 } 398 399 public void await() throws InterruptedException { 400 Thread currentThread = Thread.currentThread(); 401 402 if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException (); } 403 if (Thread.interrupted()) { throw new InterruptedException (); } 404 405 int numOfHolds = originalLock.getHoldCount(); 406 try { 407 ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE); 408 UnsafeUtil.monitorEnter(realCondition); 409 boolean isLockInUnshared = isLockRealConditionInUnshared(); 410 try { 411 fullRelease(); 412 413 waitingThreads.add(currentThread); 414 numOfWaitingThreards++; 415 416 addWaitOnUnshared(); 417 try { 418 ManagerUtil.objectWait0(realCondition); 419 } finally { 420 waitOnUnshared.remove(currentThread); 421 waitingThreads.remove(currentThread); 422 numOfWaitingThreards--; 423 } 424 } finally { 425 UnsafeUtil.monitorExit(realCondition); 426 if (!isLockInUnshared) { 427 ManagerUtil.monitorExit(realCondition); 428 } 429 } 430 } catch (TCRuntimeException e) { 431 checkCauseAndThrowInterruptedExceptionIfNecessary(e); 432 } finally { 433 reacquireLock(numOfHolds); 434 } 435 } 436 437 public void awaitUninterruptibly() { 438 Thread currentThread = Thread.currentThread(); 439 440 if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException (); } 441 442 int numOfHolds = originalLock.getHoldCount(); 443 boolean isInterrupted = false; 444 try { 445 ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE); 446 UnsafeUtil.monitorEnter(realCondition); 447 boolean isLockInUnshared = isLockRealConditionInUnshared(); 448 try { 449 fullRelease(); 450 signal = NOT_SIGNALLED; 451 while (signal == NOT_SIGNALLED) { 452 waitingThreads.add(currentThread); 453 numOfWaitingThreards++; 454 455 addWaitOnUnshared(); 456 try { 457 ManagerUtil.objectWait0(realCondition); 458 } catch (InterruptedException e) { 459 isInterrupted = true; 460 } finally { 461 waitOnUnshared.remove(currentThread); 462 waitingThreads.remove(currentThread); 463 numOfWaitingThreards--; 464 } 465 } 466 } finally { 467 UnsafeUtil.monitorExit(realCondition); 468 if (!isLockInUnshared) { 469 ManagerUtil.monitorExit(realCondition); 470 } 471 } 472 } finally { 473 reacquireLock(numOfHolds); 474 } 475 476 if (isInterrupted) { 477 currentThread.interrupt(); 478 } 479 } 480 481 public long awaitNanos(long nanosTimeout) throws InterruptedException { 482 Thread currentThread = Thread.currentThread(); 483 484 if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException (); } 485 if (Thread.interrupted()) { throw new InterruptedException (); } 486 487 int numOfHolds = originalLock.getHoldCount(); 488 try { 489 ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE); 490 UnsafeUtil.monitorEnter(realCondition); 491 boolean isLockInUnshared = isLockRealConditionInUnshared(); 492 try { 493 fullRelease(); 494 waitingThreads.add(currentThread); 495 numOfWaitingThreards++; 496 497 addWaitOnUnshared(); 498 try { 499 long startTime = getSystemNanos(); 500 TimeUnit.NANOSECONDS.timedWait(realCondition, nanosTimeout); 501 long remainingTime = nanosTimeout - (getSystemNanos() - startTime); 502 return remainingTime; 503 } finally { 504 waitOnUnshared.remove(currentThread); 505 waitingThreads.remove(currentThread); 506 numOfWaitingThreards--; 507 } 508 } finally { 509 UnsafeUtil.monitorExit(realCondition); 510 if (!isLockInUnshared) { 511 ManagerUtil.monitorExit(realCondition); 512 } 513 } 514 } catch (TCRuntimeException e) { 515 checkCauseAndThrowInterruptedExceptionIfNecessary(e); 516 return 0; 517 } finally { 518 reacquireLock(numOfHolds); 519 } 520 } 521 522 public boolean await(long time, TimeUnit unit) throws InterruptedException { 523 if (unit == null) { throw new NullPointerException (); } 524 return awaitNanos(unit.toNanos(time)) > 0; 525 } 526 527 public boolean awaitUntil(Date deadline) throws InterruptedException { 528 if (deadline == null) { throw new NullPointerException (); } 529 530 long abstime = deadline.getTime(); 531 if (System.currentTimeMillis() > abstime) { return true; } 532 return !await(abstime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); 533 } 534 535 private boolean hasWaitOnUnshared() { 536 return waitOnUnshared.values().contains(Boolean.TRUE); 537 } 538 539 public void signal() { 540 if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException (); } 541 542 ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE); 543 UnsafeUtil.monitorEnter(realCondition); 544 boolean isLockInUnshared = isLockRealConditionInUnshared(); 545 try { 546 ManagerUtil.objectNotify(realCondition); 547 if (hasWaitOnUnshared()) { 548 realCondition.notify(); 549 } 550 signal = SIGNALLED; 551 } finally { 552 UnsafeUtil.monitorExit(realCondition); 553 if (!isLockInUnshared) { 554 ManagerUtil.monitorExit(realCondition); 555 } 556 } 557 558 } 559 560 public void signalAll() { 561 if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException (); } 562 ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE); 563 UnsafeUtil.monitorEnter(realCondition); 564 boolean isLockInUnshared = isLockRealConditionInUnshared(); 565 try { 566 ManagerUtil.objectNotifyAll(realCondition); 567 if (hasWaitOnUnshared()) { 568 realCondition.notifyAll(); 569 } 570 signal = SIGNALLED; 571 } finally { 572 UnsafeUtil.monitorExit(realCondition); 573 if (!isLockInUnshared) { 574 ManagerUtil.monitorExit(realCondition); 575 } 576 } 577 } 578 579 int getWaitQueueLength(ReentrantLock lock) { 580 if (originalLock != lock) throw new IllegalArgumentException ("not owner"); 581 if (!ManagerUtil.isManaged(originalLock)) { 582 return numOfWaitingThreards; 583 } else { 584 return ManagerUtil.waitLength(realCondition); 585 } 586 } 587 588 Collection getWaitingThreads(ReentrantLock lock) { 589 if (originalLock != lock) throw new IllegalArgumentException ("not owner"); 590 return waitingThreads; 591 } 592 593 private void readObject(java.io.ObjectInputStream s) throws java.io.IOException , ClassNotFoundException { 594 s.defaultReadObject(); 595 this.waitingThreads = new ArrayList (); 596 this.numOfWaitingThreards = 0; 597 this.waitOnUnshared = new HashMap (); 598 this.signal = NOT_SIGNALLED; 599 } 600 601 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { 602 s.defaultWriteObject(); 603 } 604 605 } 606 } 607 | Popular Tags |