1 21 22 package com.rift.coad.util.lock; 24 25 import java.util.Map ; 27 import java.util.HashMap ; 28 import java.util.concurrent.ConcurrentHashMap ; 29 30 import org.apache.log4j.Logger; 32 33 34 55 public class ObjectLockFactory { 56 57 60 public class Lock { 61 public final static int READ_LOCK = 0; 63 public final static int THREAD_BOUND = 1; 64 public final static int NAME_BOUND = 2; 65 66 private long threadId = 0; 68 private long lockCount = 0; 69 private Object name = null; 70 private Map readLock = new HashMap (); 71 private int waiting = 0; 72 73 76 public Lock() { 77 78 } 79 80 81 86 public long getThreadId() { 87 return threadId; 88 } 89 90 91 96 public void setThreadId(long threadId) { 97 this.threadId = threadId; 98 } 99 100 101 106 public Object getName() { 107 return name; 108 } 109 110 111 116 public void setName(Object name) { 117 this.name = name; 118 } 119 120 121 126 public synchronized int lockType() { 127 if (readLock.size() > 0) { 128 return READ_LOCK; 129 } else if (name == null) { 130 return THREAD_BOUND; 131 } 132 return NAME_BOUND; 133 } 134 135 136 142 public boolean ownLock() { 143 if (threadId == Thread.currentThread().getId()) { 144 return true; 145 } 146 return false; 147 } 148 149 150 156 public boolean ownLock(Object name) { 157 if (threadId == Thread.currentThread().getId()) { 158 return true; 159 } 160 if (((name == null) && (this.name == null)) || 161 ((this.name == null) && (name != null))) { 162 return false; 163 } 164 return this.name.equals(name); 165 } 166 167 168 173 public boolean isLocked() { 174 if ((threadId == 0) && (readLock.size() == 0)) { 175 return false; 176 } 177 return true; 178 } 179 180 181 186 public synchronized void getReadLock() throws LockException { 187 waiting++; 188 try { 189 Long threadId = new Long (Thread.currentThread().getId()); 190 if (readLock.containsKey(threadId)) { 191 Integer lockCount = (Integer )readLock.get(threadId); 192 readLock.put(threadId,new Integer (lockCount.intValue() + 1)); 193 return; 194 } 195 while(this.threadId != 0) { 196 wait(); 197 } 198 199 readLock.put(threadId,new Integer (1)); 201 this.threadId = 0; 202 this.name = null; 203 } catch (Exception ex) { 204 throw new LockException("Failed to aquire a lock : " + 205 ex.getMessage(),ex); 206 } finally { 207 waiting--; 208 } 209 } 210 211 212 217 public synchronized void getReadLock(Object name) throws LockException { 218 waiting++; 219 try { 220 if (readLock.containsKey(name)) { 221 Integer lockCount = (Integer )readLock.get(name); 222 readLock.put(name,new Integer (lockCount.intValue() + 1)); 223 return; 224 } 225 while(this.threadId != 0) { 226 wait(); 227 } 228 229 readLock.put(name,new Integer (1)); 231 this.threadId = 0; 232 this.name = null; 233 234 } catch (Exception ex) { 235 throw new LockException("Failed to aquire a lock : " + 236 ex.getMessage(),ex); 237 } finally { 238 waiting--; 239 } 240 } 241 242 243 246 public synchronized void getWriteLock() throws LockException { 247 waiting++; 248 try { 249 long threadId = Thread.currentThread().getId(); 250 if (this.threadId == threadId) { 251 lockCount++; 252 return; 253 } 254 while(this.threadId != 0) { 255 wait(); 256 } 257 this.threadId = threadId; 259 lockCount = 1; 260 this.name = null; 261 262 while (readLock.size() > 0) { 264 wait(); 265 } 266 267 } catch (Exception ex) { 268 throw new LockException("Failed to aquire a write lock : " + 269 ex.getMessage(),ex); 270 } finally { 271 waiting--; 272 } 273 } 274 275 276 279 public synchronized void getWriteLock(Object name) throws 280 LockException { 281 waiting++; 282 try { 283 long threadId = Thread.currentThread().getId(); 284 if (this.threadId == threadId) { 285 lockCount++; 286 this.name = name; 287 return; 288 } else if ((this.name != null) && (name != null) && 289 this.name.equals(name)) { 290 this.threadId = threadId; 291 lockCount++; 292 return; 293 } 294 while(this.threadId != 0) { 295 wait(); 296 } 297 this.threadId = threadId; 299 lockCount = 1; 300 this.name = name; 301 302 while (readLock.size() > 0) { 304 wait(); 305 } 306 307 } catch (Exception ex) { 308 throw new LockException("Failed to aquire a write lock : " + 309 ex.getMessage(),ex); 310 } finally { 311 waiting--; 312 } 313 } 314 315 316 322 public synchronized boolean releaseLock() { 323 return releaseLock(new Long (Thread.currentThread().getId())); 324 } 325 326 327 333 public synchronized boolean releaseLock(Object name) { 334 long threadId = Thread.currentThread().getId(); 335 if (readLock.size() > 0) { 336 readLock.get(threadId); 337 int intValue = ((Integer )readLock.get(name)).intValue() - 1; 338 if (intValue == 0) { 339 readLock.remove(name); 340 } else { 341 readLock.put(name,new Integer (intValue)); 342 } 343 } else if ((this.threadId == threadId) || 344 ((this.name != null) && this.name.equals(name))) { 345 lockCount--; 346 if (lockCount == 0) { 347 this.threadId = 0; 348 lockCount = 0; 349 name = null; 350 } 351 } 352 notify(); 353 if (waiting == 0) { 354 return true; 355 } 356 return false; 357 } 358 } 359 360 361 364 public class ObjectLockRef implements LockRef { 365 private Object obj = null; 367 private Lock lock = null; 368 private Object name = null; 369 370 376 public ObjectLockRef(Object obj, Lock lock) { 377 this.obj = obj; 378 this.lock = lock; 379 } 380 381 382 388 public ObjectLockRef(Object obj, Lock lock, Object name) { 389 this.obj = obj; 390 this.lock = lock; 391 this.name = name; 392 } 393 394 395 400 public Object getKey() { 401 return obj; 402 } 403 404 405 410 public long getThreadId() throws LockException { 411 if (lock.lockType() == Lock.READ_LOCK) { 412 throw new LockException("This is a read lock no unique thread " + 413 "id is present."); 414 } 415 return lock.getThreadId(); 416 } 417 418 419 424 public void setThreadId(long id) throws LockException { 425 if (lock.lockType() == Lock.READ_LOCK) { 426 throw new LockException("This is a read lock cannot set the " + 427 "thread id on it"); 428 } 429 lock.setThreadId(id); 430 } 431 432 433 438 public Object getLockName() throws LockException { 439 if (lock.lockType() == Lock.READ_LOCK) { 440 throw new LockException("This is a read lock no name associated " + 441 "with it"); 442 } 443 return lock.getName(); 444 } 445 446 447 452 public void setLockName(Object name) throws LockException { 453 if (lock.lockType() == Lock.READ_LOCK) { 454 throw new LockException("This is a read lock cannot associate a" + 455 "name with it"); 456 } 457 lock.setName(name); 458 } 459 460 461 467 public int getLockType() throws LockException { 468 if (lock.lockType() == Lock.READ_LOCK) { 469 return LockRef.READ; 470 } 471 return LockRef.WRITE; 472 } 473 474 475 478 public void release() { 479 synchronized(obj) { 480 boolean remove = false; 481 if (name == null) { 482 remove = lock.releaseLock(); 483 } else { 484 remove = lock.releaseLock(name); 485 } 486 487 if (remove) { 488 locks.remove(obj); 489 } 490 } 491 } 492 493 } 494 495 public final static int WAIT = 1; 497 public final static int WAIT_ON_NAMED = 2; 498 public final static int WAIT_ON_THREAD = 3; 499 public final static int DO_NOT_WAIT = 4; 500 501 protected static Logger log = 503 Logger.getLogger(ObjectLockFactory.class.getName()); 504 505 private static Map singletonMap = new HashMap (); 507 508 private Map locks = new ConcurrentHashMap (); 510 511 514 private ObjectLockFactory() { 515 } 516 517 518 524 public synchronized static void init() throws LockException { 525 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 526 if (!singletonMap.containsKey(loader)) { 527 singletonMap.put(loader,new ObjectLockFactory()); 528 } 529 } 530 531 532 538 public synchronized static ObjectLockFactory getInstance() throws 539 LockException { 540 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 541 ObjectLockFactory singleton = null; 542 if (singletonMap.containsKey(loader)) { 543 singleton = (ObjectLockFactory)singletonMap.get(loader); 544 } else { 545 throw new LockException("There is no object lock factory for " + 546 "this class loader"); 547 } 548 return singleton; 549 } 550 551 552 558 public synchronized static void fin() throws LockException { 559 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 560 if (singletonMap.containsKey(loader)) { 561 singletonMap.remove(loader); 562 } 563 } 564 565 566 573 public LockRef acquireWriteLock(Object key) throws LockException { 574 try { 575 Lock lock = getLock(key); 576 lock.getWriteLock(); 577 return new ObjectLockRef(key,lock); 578 } catch (Exception ex) { 579 log.error("Failed to aquire the object lock : " + 580 ex.getMessage(),ex); 581 throw new LockException("Failed to aquire the object lock : " + 582 ex.getMessage()); 583 } 584 } 585 586 587 597 public LockRef acquireWriteLock(Object key, int waitFlags) 598 throws LockException, LockConflict { 599 try { 600 Lock lock = null; 601 synchronized(key) { 602 lock = getLock(key); 603 if (lock.isLocked()) { 607 if (!lock.ownLock() && (WAIT_ON_NAMED == waitFlags) && 608 (lock.lockType() != Lock.NAME_BOUND)) { 609 log.debug("The object is currently locked" + 610 " by a thread lock."); 611 throw new LockConflict("The object is currently locked" + 612 " by a thread lock."); 613 } else if (!lock.ownLock() && (WAIT_ON_THREAD == waitFlags) && 614 (lock.lockType() != Lock.THREAD_BOUND)) { 615 log.debug("The object is currently locked" + 616 " by a named object."); 617 throw new LockConflict("The object is currently locked" + 618 " by a named lock object."); 619 } else if (!lock.ownLock() && (WAIT_ON_NAMED == waitFlags) && 620 (lock.lockType() != Lock.NAME_BOUND)) { 621 log.debug("The object is currently locked" + 622 " by a named object."); 623 throw new LockConflict("The object is currently locked" + 624 " by a named lock object."); 625 } else if (!lock.ownLock() && (DO_NOT_WAIT == waitFlags)) { 626 throw new LockConflict("The object is currently locked by " + 627 "another."); 628 } 629 } 630 } 631 lock.getWriteLock(); 632 return new ObjectLockRef(key,lock); 633 } catch (LockConflict ex) { 634 throw ex; 635 } catch (Exception ex) { 636 log.error("Failed to aquire the object lock : " + 637 ex.getMessage(),ex); 638 throw new LockException("Failed to aquire the object lock : " + 639 ex.getMessage()); 640 } 641 } 642 643 644 652 public LockRef acquireWriteLock(Object key, Object name) throws LockException { 653 try { 654 Lock lock = getLock(key); 655 lock.getWriteLock(name); 656 return new ObjectLockRef(key,lock); 657 } catch (Exception ex) { 658 log.error("Failed to aquire the object lock : " + 659 ex.getMessage(),ex); 660 throw new LockException("Failed to aquire the object lock : " + 661 ex.getMessage()); 662 } 663 } 664 665 666 677 public LockRef acquireWriteLock(Object key, Object name, int waitFlags) 678 throws LockException, LockConflict { 679 try { 680 Lock lock = null; 681 synchronized(key) { 682 lock = getLock(key); 683 if (lock.isLocked()) { 687 if (!lock.ownLock(name) && (WAIT_ON_NAMED == waitFlags) && 688 (lock.lockType() != Lock.NAME_BOUND)) { 689 log.debug("The object is currently locked" + 690 " by a thread lock."); 691 throw new LockConflict("The object is currently locked" + 692 " by a thread lock."); 693 } else if (!lock.ownLock(name) && (WAIT_ON_THREAD == waitFlags) && 694 (lock.lockType() != Lock.THREAD_BOUND)) { 695 log.debug("The object is currently locked" + 696 " by a named object."); 697 throw new LockConflict("The object is currently locked" + 698 " by a named lock object."); 699 } else if (!lock.ownLock(name) && (WAIT_ON_NAMED == waitFlags) && 700 (lock.lockType() != Lock.NAME_BOUND)) { 701 log.debug("The object is currently locked" + 702 " by a named object."); 703 throw new LockConflict("The object is currently locked" + 704 " by a named lock object."); 705 } else if (!lock.ownLock(name) && (DO_NOT_WAIT == waitFlags)) { 706 throw new LockConflict("The object is currently locked by " + 707 "another."); 708 } 709 } 710 } 711 lock.getWriteLock(name); 712 return new ObjectLockRef(key,lock); 713 } catch (LockConflict ex) { 714 throw ex; 715 } catch (Exception ex) { 716 log.error("Failed to aquire the object lock : " + 717 ex.getMessage(),ex); 718 throw new LockException("Failed to aquire the object lock : " + 719 ex.getMessage()); 720 } 721 } 722 723 724 731 public LockRef acquireReadLock(Object key) 732 throws LockException { 733 try { 734 Lock lock = getLock(key); 735 lock.getReadLock(); 736 return new ObjectLockRef(key,lock); 737 } catch (Exception ex) { 738 log.error("Failed to aquire the object lock : " + 739 ex.getMessage(),ex); 740 throw new LockException("Failed to aquire the object lock : " + 741 ex.getMessage()); 742 } 743 } 744 745 753 public LockRef acquireReadLock(Object key,Object name) 754 throws LockException { 755 try { 756 Lock lock = getLock(key); 757 lock.getReadLock(name); 758 return new ObjectLockRef(key,lock,name); 759 } catch (Exception ex) { 760 log.error("Failed to aquire the object lock : " + 761 ex.getMessage(),ex); 762 throw new LockException("Failed to aquire the object lock : " + 763 ex.getMessage()); 764 } 765 } 766 767 768 774 public void releaseLock(Object key) throws LockException { 775 try { 776 synchronized(key) { 777 Lock lock = (Lock)locks.get(key); 778 if (lock.releaseLock()) { 779 locks.remove(key); 780 } 781 } 782 } catch (Exception ex) { 783 log.error("Failed to aquire the object lock : " + 784 ex.getMessage(),ex); 785 throw new LockException("Failed to aquire the object lock : " + 786 ex.getMessage()); 787 } 788 } 789 790 791 797 public void releaseLock(Object key, Object name) throws LockException { 798 try { 799 synchronized(key) { 800 Lock lock = (Lock)locks.get(key); 801 if (lock.releaseLock(name)) { 802 locks.remove(key); 803 } 804 } 805 } catch (Exception ex) { 806 log.error("Failed to aquire the object lock : " + 807 ex.getMessage(),ex); 808 throw new LockException("Failed to aquire the object lock : " + 809 ex.getMessage()); 810 } 811 } 812 813 814 817 private Lock getLock(Object key) throws LockException { 818 synchronized (key) { 819 Lock lock = (Lock)locks.get(key); 820 if (lock == null) { 821 lock = new Lock(); 822 locks.put(key,lock); 823 } 824 return lock; 825 } 826 } 827 } 828 | Popular Tags |