├── TheArtOFMultiprocessorProgramming ├── Lock │ ├── CLHLock.java │ ├── MCSLock.java │ ├── TASLock.java │ ├── ArrayLock.java │ ├── TTASLock.java │ ├── BackoffLock.java │ ├── TimeOutLock.java │ ├── CompositeLock.java │ ├── CompositeFastPathLock.java │ └── Backoff.java ├── MonitorsAndBlockingSynchronization │ ├── Semaphore.java │ ├── FifoReadWriteLock.java │ ├── SimpleReadWriteLock.java │ └── SimpleReentrantLock.java ├── locks │ ├── AbstractOwnableSynchronizer.java │ ├── package-info.java │ ├── ReadWriteLock.java │ ├── LockSupport.java │ └── Lock.java ├── concurrent │ └── atomic │ │ ├── AtomicReference.java │ │ ├── AtomicBoolean.java │ │ ├── AtomicReferenceArray.java │ │ ├── AtomicInteger.java │ │ ├── AtomicStampedReference.java │ │ ├── AtomicMarkableReference.java │ │ ├── AtomicLong.java │ │ ├── AtomicLongArray.java │ │ ├── AtomicIntegerArray.java │ │ ├── package-info.java │ │ ├── AtomicReferenceFieldUpdater.java │ │ ├── AtomicIntegerFieldUpdater.java │ │ └── AtomicLongFieldUpdater.java ├── TheArtOFMultiprocessorProgramming.vcxproj.filters ├── TheArtOFMultiprocessorProgramming.vcxproj ├── park.hpp └── park.cpp ├── README.md ├── TheArtOFMultiprocessorProgramming.sln ├── .gitattributes └── .gitignore /TheArtOFMultiprocessorProgramming/Lock/CLHLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/CLHLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/MCSLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/MCSLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/TASLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/TASLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/ArrayLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/ArrayLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/TTASLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/TTASLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/BackoffLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/BackoffLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/TimeOutLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/TimeOutLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/CompositeLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/CompositeLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/CompositeFastPathLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/Lock/CompositeFastPathLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/Semaphore.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/Semaphore.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/FifoReadWriteLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/FifoReadWriteLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/SimpleReadWriteLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/SimpleReadWriteLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/SimpleReentrantLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zouxiaohang/TheArtOFMultiprocessorProgramming/HEAD/TheArtOFMultiprocessorProgramming/MonitorsAndBlockingSynchronization/SimpleReentrantLock.java -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/Lock/Backoff.java: -------------------------------------------------------------------------------- 1 | import java.util.Random; 2 | 3 | public class Backoff{ 4 | final int minDelay, maxDelay; 5 | int limit; 6 | final Random random; 7 | 8 | public Backoff(int min, int max){ 9 | minDelay = min; 10 | maxDelay = max; 11 | limit = min; 12 | random = new Random(); 13 | } 14 | public void backoff() throws InterruptedException{ 15 | int delay = random.nextInt(limit); 16 | limit = Math.min(maxDelay, 2 * limit); 17 | Thread.sleep(delay); 18 | } 19 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The Art Of Multiprocessor Programming 2 | ================================= 3 | 4 | 多处理器编程的艺术 5 | ================== 6 | 7 | #####完成《多处理器编程的艺术》这本书上的所有示例代码,并给出自己的评注,包括对代码的注释、分析和书中示例代码出现的bug 8 | 9 | * Chapter 7: 10 | * TASLock 11 | * TTASLock 12 | * ArrayLock 13 | * BackoffLock 14 | * CLHLock 15 | * MCSLock 16 | * TimeOutLock 17 | * CompositeLock 18 | * CompositeFastPathLock 19 | * Chapter 8: 20 | * SimpleReadWriteLock 21 | * FifoReadWriteLock 22 | * Semaphore 23 | * SimpleReentrantLock 24 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TheArtOFMultiprocessorProgramming", "TheArtOFMultiprocessorProgramming\TheArtOFMultiprocessorProgramming.vcxproj", "{0218C742-7542-449E-BA33-98E9BB64193D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {0218C742-7542-449E-BA33-98E9BB64193D}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {0218C742-7542-449E-BA33-98E9BB64193D}.Debug|Win32.Build.0 = Debug|Win32 16 | {0218C742-7542-449E-BA33-98E9BB64193D}.Release|Win32.ActiveCfg = Release|Win32 17 | {0218C742-7542-449E-BA33-98E9BB64193D}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | #packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | 136 | #LightSwitch generated files 137 | GeneratedArtifacts/ 138 | _Pvt_Extensions/ 139 | ModelManifest.xml 140 | 141 | # ========================= 142 | # Windows detritus 143 | # ========================= 144 | 145 | # Windows image file caches 146 | Thumbs.db 147 | ehthumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | # Recycle Bin used on file shares 153 | $RECYCLE.BIN/ 154 | 155 | # Mac desktop service store files 156 | .DS_Store 157 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/locks/AbstractOwnableSynchronizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.locks; 37 | 38 | /** 39 | * A synchronizer that may be exclusively owned by a thread. This 40 | * class provides a basis for creating locks and related synchronizers 41 | * that may entail a notion of ownership. The 42 | * AbstractOwnableSynchronizer class itself does not manage or 43 | * use this information. However, subclasses and tools may use 44 | * appropriately maintained values to help control and monitor access 45 | * and provide diagnostics. 46 | * 47 | * @since 1.6 48 | * @author Doug Lea 49 | */ 50 | public abstract class AbstractOwnableSynchronizer 51 | implements java.io.Serializable { 52 | 53 | /** Use serial ID even though all fields transient. */ 54 | private static final long serialVersionUID = 3737899427754241961L; 55 | 56 | /** 57 | * Empty constructor for use by subclasses. 58 | */ 59 | protected AbstractOwnableSynchronizer() { } 60 | 61 | /** 62 | * The current owner of exclusive mode synchronization. 63 | */ 64 | private transient Thread exclusiveOwnerThread; 65 | 66 | /** 67 | * Sets the thread that currently owns exclusive access. A 68 | * null argument indicates that no thread owns access. 69 | * This method does not otherwise impose any synchronization or 70 | * volatile field accesses. 71 | */ 72 | protected final void setExclusiveOwnerThread(Thread t) { 73 | exclusiveOwnerThread = t; 74 | } 75 | 76 | /** 77 | * Returns the thread last set by 78 | * setExclusiveOwnerThread, or null if never 79 | * set. This method does not otherwise impose any synchronization 80 | * or volatile field accesses. 81 | * @return the owner thread 82 | */ 83 | protected final Thread getExclusiveOwnerThread() { 84 | return exclusiveOwnerThread; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/locks/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | /** 37 | * Interfaces and classes providing a framework for locking and waiting 38 | * for conditions that is distinct from built-in synchronization and 39 | * monitors. The framework permits much greater flexibility in the use of 40 | * locks and conditions, at the expense of more awkward syntax. 41 | * 42 | *

The {@link java.util.concurrent.locks.Lock} interface supports 43 | * locking disciplines that differ in semantics (reentrant, fair, etc), 44 | * and that can be used in non-block-structured contexts including 45 | * hand-over-hand and lock reordering algorithms. The main implementation 46 | * is {@link java.util.concurrent.locks.ReentrantLock}. 47 | * 48 | *

The {@link java.util.concurrent.locks.ReadWriteLock} interface 49 | * similarly defines locks that may be shared among readers but are 50 | * exclusive to writers. Only a single implementation, {@link 51 | * java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since 52 | * it covers most standard usage contexts. But programmers may create 53 | * their own implementations to cover nonstandard requirements. 54 | * 55 | *

The {@link java.util.concurrent.locks.Condition} interface 56 | * describes condition variables that may be associated with Locks. 57 | * These are similar in usage to the implicit monitors accessed using 58 | * {@code Object.wait}, but offer extended capabilities. 59 | * In particular, multiple {@code Condition} objects may be associated 60 | * with a single {@code Lock}. To avoid compatibility issues, the 61 | * names of {@code Condition} methods are different from the 62 | * corresponding {@code Object} versions. 63 | * 64 | *

The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer} 65 | * class serves as a useful superclass for defining locks and other 66 | * synchronizers that rely on queuing blocked threads. The {@link 67 | * java.util.concurrent.locks.AbstractQueuedLongSynchronizer} class 68 | * provides the same functionality but extends support to 64 bits of 69 | * synchronization state. Both extend class {@link 70 | * java.util.concurrent.locks.AbstractOwnableSynchronizer}, a simple 71 | * class that helps record the thread currently holding exclusive 72 | * synchronization. The {@link java.util.concurrent.locks.LockSupport} 73 | * class provides lower-level blocking and unblocking support that is 74 | * useful for those developers implementing their own customized lock 75 | * classes. 76 | * 77 | * @since 1.5 78 | */ 79 | package java.util.concurrent.locks; 80 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | 39 | /** 40 | * An object reference that may be updated atomically. See the {@link 41 | * java.util.concurrent.atomic} package specification for description 42 | * of the properties of atomic variables. 43 | * @since 1.5 44 | * @author Doug Lea 45 | * @param The type of object referred to by this reference 46 | */ 47 | public class AtomicReference implements java.io.Serializable { 48 | private static final long serialVersionUID = -1848883965231344442L; 49 | 50 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 51 | private static final long valueOffset; 52 | 53 | static { 54 | try { 55 | valueOffset = unsafe.objectFieldOffset 56 | (AtomicReference.class.getDeclaredField("value")); 57 | } catch (Exception ex) { throw new Error(ex); } 58 | } 59 | 60 | private volatile V value; 61 | 62 | /** 63 | * Creates a new AtomicReference with the given initial value. 64 | * 65 | * @param initialValue the initial value 66 | */ 67 | public AtomicReference(V initialValue) { 68 | value = initialValue; 69 | } 70 | 71 | /** 72 | * Creates a new AtomicReference with null initial value. 73 | */ 74 | public AtomicReference() { 75 | } 76 | 77 | /** 78 | * Gets the current value. 79 | * 80 | * @return the current value 81 | */ 82 | public final V get() { 83 | return value; 84 | } 85 | 86 | /** 87 | * Sets to the given value. 88 | * 89 | * @param newValue the new value 90 | */ 91 | public final void set(V newValue) { 92 | value = newValue; 93 | } 94 | 95 | /** 96 | * Eventually sets to the given value. 97 | * 98 | * @param newValue the new value 99 | * @since 1.6 100 | */ 101 | public final void lazySet(V newValue) { 102 | unsafe.putOrderedObject(this, valueOffset, newValue); 103 | } 104 | 105 | /** 106 | * Atomically sets the value to the given updated value 107 | * if the current value {@code ==} the expected value. 108 | * @param expect the expected value 109 | * @param update the new value 110 | * @return true if successful. False return indicates that 111 | * the actual value was not equal to the expected value. 112 | */ 113 | public final boolean compareAndSet(V expect, V update) { 114 | return unsafe.compareAndSwapObject(this, valueOffset, expect, update); 115 | } 116 | 117 | /** 118 | * Atomically sets the value to the given updated value 119 | * if the current value {@code ==} the expected value. 120 | * 121 | *

May fail spuriously 122 | * and does not provide ordering guarantees, so is only rarely an 123 | * appropriate alternative to {@code compareAndSet}. 124 | * 125 | * @param expect the expected value 126 | * @param update the new value 127 | * @return true if successful. 128 | */ 129 | public final boolean weakCompareAndSet(V expect, V update) { 130 | return unsafe.compareAndSwapObject(this, valueOffset, expect, update); 131 | } 132 | 133 | /** 134 | * Atomically sets to the given value and returns the old value. 135 | * 136 | * @param newValue the new value 137 | * @return the previous value 138 | */ 139 | public final V getAndSet(V newValue) { 140 | while (true) { 141 | V x = get(); 142 | if (compareAndSet(x, newValue)) 143 | return x; 144 | } 145 | } 146 | 147 | /** 148 | * Returns the String representation of the current value. 149 | * @return the String representation of the current value. 150 | */ 151 | public String toString() { 152 | return String.valueOf(get()); 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/TheArtOFMultiprocessorProgramming.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {91e27911-b0ef-40eb-a94a-1a3e0e891444} 6 | 7 | 8 | {f55754a5-bc1b-4c51-b8fd-6c24f93864b3} 9 | 10 | 11 | {27abf886-00a8-49c4-9f7e-e0a27509dcaf} 12 | 13 | 14 | {3b29f8db-1b16-45ef-9552-5a3226cf37e1} 15 | 16 | 17 | {875fad95-17ea-4003-8fe3-3a3e8b346af2} 18 | 19 | 20 | 21 | 22 | Lock 23 | 24 | 25 | Lock 26 | 27 | 28 | Lock 29 | 30 | 31 | Lock 32 | 33 | 34 | Lock 35 | 36 | 37 | Lock 38 | 39 | 40 | Lock 41 | 42 | 43 | Lock 44 | 45 | 46 | Lock 47 | 48 | 49 | Lock 50 | 51 | 52 | MonitorsAndBlockingSynchronization 53 | 54 | 55 | MonitorsAndBlockingSynchronization 56 | 57 | 58 | MonitorsAndBlockingSynchronization 59 | 60 | 61 | MonitorsAndBlockingSynchronization 62 | 63 | 64 | JavaConcurrent\Atomic 65 | 66 | 67 | JavaConcurrent\Atomic 68 | 69 | 70 | JavaConcurrent\Atomic 71 | 72 | 73 | JavaConcurrent\Atomic 74 | 75 | 76 | JavaConcurrent\Atomic 77 | 78 | 79 | JavaConcurrent\Atomic 80 | 81 | 82 | JavaConcurrent\Atomic 83 | 84 | 85 | JavaConcurrent\Atomic 86 | 87 | 88 | JavaConcurrent\Atomic 89 | 90 | 91 | JavaConcurrent\Atomic 92 | 93 | 94 | JavaConcurrent\Atomic 95 | 96 | 97 | JavaConcurrent\Atomic 98 | 99 | 100 | JavaConcurrent\Atomic 101 | 102 | 103 | 104 | JavaConcurrent\Locks 105 | 106 | 107 | JavaConcurrent\Locks 108 | 109 | 110 | JavaConcurrent\Locks 111 | 112 | 113 | JavaConcurrent\Locks 114 | 115 | 116 | JavaConcurrent\Locks 117 | 118 | 119 | JavaConcurrent\Locks 120 | 121 | 122 | JavaConcurrent\Locks 123 | 124 | 125 | JavaConcurrent\Locks 126 | 127 | 128 | JavaConcurrent\Locks 129 | 130 | 131 | JavaConcurrent\Locks 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicBoolean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | 39 | /** 40 | * A {@code boolean} value that may be updated atomically. See the 41 | * {@link java.util.concurrent.atomic} package specification for 42 | * description of the properties of atomic variables. An 43 | * {@code AtomicBoolean} is used in applications such as atomically 44 | * updated flags, and cannot be used as a replacement for a 45 | * {@link java.lang.Boolean}. 46 | * 47 | * @since 1.5 48 | * @author Doug Lea 49 | */ 50 | public class AtomicBoolean implements java.io.Serializable { 51 | private static final long serialVersionUID = 4654671469794556979L; 52 | // setup to use Unsafe.compareAndSwapInt for updates 53 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 54 | private static final long valueOffset; 55 | 56 | static { 57 | try { 58 | valueOffset = unsafe.objectFieldOffset 59 | (AtomicBoolean.class.getDeclaredField("value")); 60 | } catch (Exception ex) { throw new Error(ex); } 61 | } 62 | 63 | private volatile int value; 64 | 65 | /** 66 | * Creates a new {@code AtomicBoolean} with the given initial value. 67 | * 68 | * @param initialValue the initial value 69 | */ 70 | public AtomicBoolean(boolean initialValue) { 71 | value = initialValue ? 1 : 0; 72 | } 73 | 74 | /** 75 | * Creates a new {@code AtomicBoolean} with initial value {@code false}. 76 | */ 77 | public AtomicBoolean() { 78 | } 79 | 80 | /** 81 | * Returns the current value. 82 | * 83 | * @return the current value 84 | */ 85 | public final boolean get() { 86 | return value != 0; 87 | } 88 | 89 | /** 90 | * Atomically sets the value to the given updated value 91 | * if the current value {@code ==} the expected value. 92 | * 93 | * @param expect the expected value 94 | * @param update the new value 95 | * @return true if successful. False return indicates that 96 | * the actual value was not equal to the expected value. 97 | */ 98 | public final boolean compareAndSet(boolean expect, boolean update) { 99 | int e = expect ? 1 : 0; 100 | int u = update ? 1 : 0; 101 | return unsafe.compareAndSwapInt(this, valueOffset, e, u); 102 | } 103 | 104 | /** 105 | * Atomically sets the value to the given updated value 106 | * if the current value {@code ==} the expected value. 107 | * 108 | *

May fail spuriously 109 | * and does not provide ordering guarantees, so is only rarely an 110 | * appropriate alternative to {@code compareAndSet}. 111 | * 112 | * @param expect the expected value 113 | * @param update the new value 114 | * @return true if successful. 115 | */ 116 | public boolean weakCompareAndSet(boolean expect, boolean update) { 117 | int e = expect ? 1 : 0; 118 | int u = update ? 1 : 0; 119 | return unsafe.compareAndSwapInt(this, valueOffset, e, u); 120 | } 121 | 122 | /** 123 | * Unconditionally sets to the given value. 124 | * 125 | * @param newValue the new value 126 | */ 127 | public final void set(boolean newValue) { 128 | value = newValue ? 1 : 0; 129 | } 130 | 131 | /** 132 | * Eventually sets to the given value. 133 | * 134 | * @param newValue the new value 135 | * @since 1.6 136 | */ 137 | public final void lazySet(boolean newValue) { 138 | int v = newValue ? 1 : 0; 139 | unsafe.putOrderedInt(this, valueOffset, v); 140 | } 141 | 142 | /** 143 | * Atomically sets to the given value and returns the previous value. 144 | * 145 | * @param newValue the new value 146 | * @return the previous value 147 | */ 148 | public final boolean getAndSet(boolean newValue) { 149 | for (;;) { 150 | boolean current = get(); 151 | if (compareAndSet(current, newValue)) 152 | return current; 153 | } 154 | } 155 | 156 | /** 157 | * Returns the String representation of the current value. 158 | * @return the String representation of the current value. 159 | */ 160 | public String toString() { 161 | return Boolean.toString(get()); 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/locks/ReadWriteLock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.locks; 37 | 38 | /** 39 | * A ReadWriteLock maintains a pair of associated {@link 40 | * Lock locks}, one for read-only operations and one for writing. 41 | * The {@link #readLock read lock} may be held simultaneously by 42 | * multiple reader threads, so long as there are no writers. The 43 | * {@link #writeLock write lock} is exclusive. 44 | * 45 | *

All ReadWriteLock implementations must guarantee that 46 | * the memory synchronization effects of writeLock operations 47 | * (as specified in the {@link Lock} interface) also hold with respect 48 | * to the associated readLock. That is, a thread successfully 49 | * acquiring the read lock will see all updates made upon previous 50 | * release of the write lock. 51 | * 52 | *

A read-write lock allows for a greater level of concurrency in 53 | * accessing shared data than that permitted by a mutual exclusion lock. 54 | * It exploits the fact that while only a single thread at a time (a 55 | * writer thread) can modify the shared data, in many cases any 56 | * number of threads can concurrently read the data (hence reader 57 | * threads). 58 | * In theory, the increase in concurrency permitted by the use of a read-write 59 | * lock will lead to performance improvements over the use of a mutual 60 | * exclusion lock. In practice this increase in concurrency will only be fully 61 | * realized on a multi-processor, and then only if the access patterns for 62 | * the shared data are suitable. 63 | * 64 | *

Whether or not a read-write lock will improve performance over the use 65 | * of a mutual exclusion lock depends on the frequency that the data is 66 | * read compared to being modified, the duration of the read and write 67 | * operations, and the contention for the data - that is, the number of 68 | * threads that will try to read or write the data at the same time. 69 | * For example, a collection that is initially populated with data and 70 | * thereafter infrequently modified, while being frequently searched 71 | * (such as a directory of some kind) is an ideal candidate for the use of 72 | * a read-write lock. However, if updates become frequent then the data 73 | * spends most of its time being exclusively locked and there is little, if any 74 | * increase in concurrency. Further, if the read operations are too short 75 | * the overhead of the read-write lock implementation (which is inherently 76 | * more complex than a mutual exclusion lock) can dominate the execution 77 | * cost, particularly as many read-write lock implementations still serialize 78 | * all threads through a small section of code. Ultimately, only profiling 79 | * and measurement will establish whether the use of a read-write lock is 80 | * suitable for your application. 81 | * 82 | * 83 | *

Although the basic operation of a read-write lock is straight-forward, 84 | * there are many policy decisions that an implementation must make, which 85 | * may affect the effectiveness of the read-write lock in a given application. 86 | * Examples of these policies include: 87 | *

109 | * You should consider all of these things when evaluating the suitability 110 | * of a given implementation for your application. 111 | * 112 | * @see ReentrantReadWriteLock 113 | * @see Lock 114 | * @see ReentrantLock 115 | * 116 | * @since 1.5 117 | * @author Doug Lea 118 | */ 119 | public interface ReadWriteLock { 120 | /** 121 | * Returns the lock used for reading. 122 | * 123 | * @return the lock used for reading. 124 | */ 125 | Lock readLock(); 126 | 127 | /** 128 | * Returns the lock used for writing. 129 | * 130 | * @return the lock used for writing. 131 | */ 132 | Lock writeLock(); 133 | } 134 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/TheArtOFMultiprocessorProgramming.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {0218C742-7542-449E-BA33-98E9BB64193D} 15 | Win32Proj 16 | TheArtOFMultiprocessorProgramming 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | 56 | 57 | Console 58 | true 59 | 60 | 61 | 62 | 63 | Level3 64 | 65 | 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 70 | 71 | 72 | Console 73 | true 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/park.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 | * or visit www.oracle.com if you need additional information or have any 21 | * questions. 22 | * 23 | */ 24 | 25 | #ifndef SHARE_VM_RUNTIME_PARK_HPP 26 | #define SHARE_VM_RUNTIME_PARK_HPP 27 | 28 | #include "utilities/debug.hpp" 29 | #include "utilities/globalDefinitions.hpp" 30 | /* 31 | * Per-thread blocking support for JSR166. See the Java-level 32 | * Documentation for rationale. Basically, park acts like wait, unpark 33 | * like notify. 34 | * 35 | * 6271289 -- 36 | * To avoid errors where an os thread expires but the JavaThread still 37 | * exists, Parkers are immortal (type-stable) and are recycled across 38 | * new threads. This parallels the ParkEvent implementation. 39 | * Because park-unpark allow spurious wakeups it is harmless if an 40 | * unpark call unparks a new thread using the old Parker reference. 41 | * 42 | * In the future we'll want to think about eliminating Parker and using 43 | * ParkEvent instead. There's considerable duplication between the two 44 | * services. 45 | * 46 | */ 47 | 48 | class Parker : public os::PlatformParker { 49 | private: 50 | volatile int _counter ; 51 | Parker * FreeNext ; 52 | JavaThread * AssociatedWith ; // Current association 53 | 54 | public: 55 | Parker() : PlatformParker() { 56 | _counter = 0 ; 57 | FreeNext = NULL ; 58 | AssociatedWith = NULL ; 59 | } 60 | protected: 61 | ~Parker() { ShouldNotReachHere(); } 62 | public: 63 | // For simplicity of interface with Java, all forms of park (indefinite, 64 | // relative, and absolute) are multiplexed into one call. 65 | void park(bool isAbsolute, jlong time); 66 | void unpark(); 67 | 68 | // Lifecycle operators 69 | static Parker * Allocate (JavaThread * t) ; 70 | static void Release (Parker * e) ; 71 | private: 72 | static Parker * volatile FreeList ; 73 | static volatile int ListLock ; 74 | 75 | }; 76 | 77 | ///////////////////////////////////////////////////////////// 78 | // 79 | // ParkEvents are type-stable and immortal. 80 | // 81 | // Lifecycle: Once a ParkEvent is associated with a thread that ParkEvent remains 82 | // associated with the thread for the thread's entire lifetime - the relationship is 83 | // stable. A thread will be associated at most one ParkEvent. When the thread 84 | // expires, the ParkEvent moves to the EventFreeList. New threads attempt to allocate from 85 | // the EventFreeList before creating a new Event. Type-stability frees us from 86 | // worrying about stale Event or Thread references in the objectMonitor subsystem. 87 | // (A reference to ParkEvent is always valid, even though the event may no longer be associated 88 | // with the desired or expected thread. A key aspect of this design is that the callers of 89 | // park, unpark, etc must tolerate stale references and spurious wakeups). 90 | // 91 | // Only the "associated" thread can block (park) on the ParkEvent, although 92 | // any other thread can unpark a reachable parkevent. Park() is allowed to 93 | // return spuriously. In fact park-unpark a really just an optimization to 94 | // avoid unbounded spinning and surrender the CPU to be a polite system citizen. 95 | // A degenerate albeit "impolite" park-unpark implementation could simply return. 96 | // See http://blogs.sun.com/dave for more details. 97 | // 98 | // Eventually I'd like to eliminate Events and ObjectWaiters, both of which serve as 99 | // thread proxies, and simply make the THREAD structure type-stable and persistent. 100 | // Currently, we unpark events associated with threads, but ideally we'd just 101 | // unpark threads. 102 | // 103 | // The base-class, PlatformEvent, is platform-specific while the ParkEvent is 104 | // platform-independent. PlatformEvent provides park(), unpark(), etc., and 105 | // is abstract -- that is, a PlatformEvent should never be instantiated except 106 | // as part of a ParkEvent. 107 | // Equivalently we could have defined a platform-independent base-class that 108 | // exported Allocate(), Release(), etc. The platform-specific class would extend 109 | // that base-class, adding park(), unpark(), etc. 110 | // 111 | // A word of caution: The JVM uses 2 very similar constructs: 112 | // 1. ParkEvent are used for Java-level "monitor" synchronization. 113 | // 2. Parkers are used by JSR166-JUC park-unpark. 114 | // 115 | // We'll want to eventually merge these redundant facilities and use ParkEvent. 116 | 117 | 118 | class ParkEvent : public os::PlatformEvent { 119 | private: 120 | ParkEvent * FreeNext ; 121 | 122 | // Current association 123 | Thread * AssociatedWith ; 124 | intptr_t RawThreadIdentity ; // LWPID etc 125 | volatile int Incarnation ; 126 | 127 | // diagnostic : keep track of last thread to wake this thread. 128 | // this is useful for construction of dependency graphs. 129 | void * LastWaker ; 130 | 131 | public: 132 | // MCS-CLH list linkage and Native Mutex/Monitor 133 | ParkEvent * volatile ListNext ; 134 | ParkEvent * volatile ListPrev ; 135 | volatile intptr_t OnList ; 136 | volatile int TState ; 137 | volatile int Notified ; // for native monitor construct 138 | volatile int IsWaiting ; // Enqueued on WaitSet 139 | 140 | 141 | private: 142 | static ParkEvent * volatile FreeList ; 143 | static volatile int ListLock ; 144 | 145 | // It's prudent to mark the dtor as "private" 146 | // ensuring that it's not visible outside the package. 147 | // Unfortunately gcc warns about such usage, so 148 | // we revert to the less desirable "protected" visibility. 149 | // The other compilers accept private dtors. 150 | 151 | protected: // Ensure dtor is never invoked 152 | ~ParkEvent() { guarantee (0, "invariant") ; } 153 | 154 | ParkEvent() : PlatformEvent() { 155 | AssociatedWith = NULL ; 156 | FreeNext = NULL ; 157 | ListNext = NULL ; 158 | ListPrev = NULL ; 159 | OnList = 0 ; 160 | TState = 0 ; 161 | Notified = 0 ; 162 | IsWaiting = 0 ; 163 | } 164 | 165 | // We use placement-new to force ParkEvent instances to be 166 | // aligned on 256-byte address boundaries. This ensures that the least 167 | // significant byte of a ParkEvent address is always 0. 168 | 169 | void * operator new (size_t sz) ; 170 | void operator delete (void * a) ; 171 | 172 | public: 173 | static ParkEvent * Allocate (Thread * t) ; 174 | static void Release (ParkEvent * e) ; 175 | } ; 176 | 177 | #endif // SHARE_VM_RUNTIME_PARK_HPP 178 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicReferenceArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | import java.util.*; 39 | 40 | /** 41 | * An array of object references in which elements may be updated 42 | * atomically. See the {@link java.util.concurrent.atomic} package 43 | * specification for description of the properties of atomic 44 | * variables. 45 | * @since 1.5 46 | * @author Doug Lea 47 | * @param The base class of elements held in this array 48 | */ 49 | public class AtomicReferenceArray implements java.io.Serializable { 50 | private static final long serialVersionUID = -6209656149925076980L; 51 | 52 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 53 | private static final int base = unsafe.arrayBaseOffset(Object[].class); 54 | private static final int shift; 55 | private final Object[] array; 56 | 57 | static { 58 | int scale = unsafe.arrayIndexScale(Object[].class); 59 | if ((scale & (scale - 1)) != 0) 60 | throw new Error("data type scale not a power of two"); 61 | shift = 31 - Integer.numberOfLeadingZeros(scale); 62 | } 63 | 64 | private long checkedByteOffset(int i) { 65 | if (i < 0 || i >= array.length) 66 | throw new IndexOutOfBoundsException("index " + i); 67 | 68 | return byteOffset(i); 69 | } 70 | 71 | private static long byteOffset(int i) { 72 | return ((long) i << shift) + base; 73 | } 74 | 75 | /** 76 | * Creates a new AtomicReferenceArray of the given length, with all 77 | * elements initially null. 78 | * 79 | * @param length the length of the array 80 | */ 81 | public AtomicReferenceArray(int length) { 82 | array = new Object[length]; 83 | } 84 | 85 | /** 86 | * Creates a new AtomicReferenceArray with the same length as, and 87 | * all elements copied from, the given array. 88 | * 89 | * @param array the array to copy elements from 90 | * @throws NullPointerException if array is null 91 | */ 92 | public AtomicReferenceArray(E[] array) { 93 | // Visibility guaranteed by final field guarantees 94 | this.array = array.clone(); 95 | } 96 | 97 | /** 98 | * Returns the length of the array. 99 | * 100 | * @return the length of the array 101 | */ 102 | public final int length() { 103 | return array.length; 104 | } 105 | 106 | /** 107 | * Gets the current value at position {@code i}. 108 | * 109 | * @param i the index 110 | * @return the current value 111 | */ 112 | public final E get(int i) { 113 | return getRaw(checkedByteOffset(i)); 114 | } 115 | 116 | private E getRaw(long offset) { 117 | return (E) unsafe.getObjectVolatile(array, offset); 118 | } 119 | 120 | /** 121 | * Sets the element at position {@code i} to the given value. 122 | * 123 | * @param i the index 124 | * @param newValue the new value 125 | */ 126 | public final void set(int i, E newValue) { 127 | unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue); 128 | } 129 | 130 | /** 131 | * Eventually sets the element at position {@code i} to the given value. 132 | * 133 | * @param i the index 134 | * @param newValue the new value 135 | * @since 1.6 136 | */ 137 | public final void lazySet(int i, E newValue) { 138 | unsafe.putOrderedObject(array, checkedByteOffset(i), newValue); 139 | } 140 | 141 | 142 | /** 143 | * Atomically sets the element at position {@code i} to the given 144 | * value and returns the old value. 145 | * 146 | * @param i the index 147 | * @param newValue the new value 148 | * @return the previous value 149 | */ 150 | public final E getAndSet(int i, E newValue) { 151 | long offset = checkedByteOffset(i); 152 | while (true) { 153 | E current = (E) getRaw(offset); 154 | if (compareAndSetRaw(offset, current, newValue)) 155 | return current; 156 | } 157 | } 158 | 159 | /** 160 | * Atomically sets the element at position {@code i} to the given 161 | * updated value if the current value {@code ==} the expected value. 162 | * 163 | * @param i the index 164 | * @param expect the expected value 165 | * @param update the new value 166 | * @return true if successful. False return indicates that 167 | * the actual value was not equal to the expected value. 168 | */ 169 | public final boolean compareAndSet(int i, E expect, E update) { 170 | return compareAndSetRaw(checkedByteOffset(i), expect, update); 171 | } 172 | 173 | private boolean compareAndSetRaw(long offset, E expect, E update) { 174 | return unsafe.compareAndSwapObject(array, offset, expect, update); 175 | } 176 | 177 | /** 178 | * Atomically sets the element at position {@code i} to the given 179 | * updated value if the current value {@code ==} the expected value. 180 | * 181 | *

May fail spuriously 182 | * and does not provide ordering guarantees, so is only rarely an 183 | * appropriate alternative to {@code compareAndSet}. 184 | * 185 | * @param i the index 186 | * @param expect the expected value 187 | * @param update the new value 188 | * @return true if successful. 189 | */ 190 | public final boolean weakCompareAndSet(int i, E expect, E update) { 191 | return compareAndSet(i, expect, update); 192 | } 193 | 194 | /** 195 | * Returns the String representation of the current values of array. 196 | * @return the String representation of the current values of array 197 | */ 198 | public String toString() { 199 | int iMax = array.length - 1; 200 | if (iMax == -1) 201 | return "[]"; 202 | 203 | StringBuilder b = new StringBuilder(); 204 | b.append('['); 205 | for (int i = 0; ; i++) { 206 | b.append(getRaw(byteOffset(i))); 207 | if (i == iMax) 208 | return b.append(']').toString(); 209 | b.append(',').append(' '); 210 | } 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicInteger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | 39 | /** 40 | * An {@code int} value that may be updated atomically. See the 41 | * {@link java.util.concurrent.atomic} package specification for 42 | * description of the properties of atomic variables. An 43 | * {@code AtomicInteger} is used in applications such as atomically 44 | * incremented counters, and cannot be used as a replacement for an 45 | * {@link java.lang.Integer}. However, this class does extend 46 | * {@code Number} to allow uniform access by tools and utilities that 47 | * deal with numerically-based classes. 48 | * 49 | * @since 1.5 50 | * @author Doug Lea 51 | */ 52 | public class AtomicInteger extends Number implements java.io.Serializable { 53 | private static final long serialVersionUID = 6214790243416807050L; 54 | 55 | // setup to use Unsafe.compareAndSwapInt for updates 56 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 57 | private static final long valueOffset; 58 | 59 | static { 60 | try { 61 | valueOffset = unsafe.objectFieldOffset 62 | (AtomicInteger.class.getDeclaredField("value")); 63 | } catch (Exception ex) { throw new Error(ex); } 64 | } 65 | 66 | private volatile int value; 67 | 68 | /** 69 | * Creates a new AtomicInteger with the given initial value. 70 | * 71 | * @param initialValue the initial value 72 | */ 73 | public AtomicInteger(int initialValue) { 74 | value = initialValue; 75 | } 76 | 77 | /** 78 | * Creates a new AtomicInteger with initial value {@code 0}. 79 | */ 80 | public AtomicInteger() { 81 | } 82 | 83 | /** 84 | * Gets the current value. 85 | * 86 | * @return the current value 87 | */ 88 | public final int get() { 89 | return value; 90 | } 91 | 92 | /** 93 | * Sets to the given value. 94 | * 95 | * @param newValue the new value 96 | */ 97 | public final void set(int newValue) { 98 | value = newValue; 99 | } 100 | 101 | /** 102 | * Eventually sets to the given value. 103 | * 104 | * @param newValue the new value 105 | * @since 1.6 106 | */ 107 | public final void lazySet(int newValue) { 108 | unsafe.putOrderedInt(this, valueOffset, newValue); 109 | } 110 | 111 | /** 112 | * Atomically sets to the given value and returns the old value. 113 | * 114 | * @param newValue the new value 115 | * @return the previous value 116 | */ 117 | public final int getAndSet(int newValue) { 118 | for (;;) { 119 | int current = get(); 120 | if (compareAndSet(current, newValue)) 121 | return current; 122 | } 123 | } 124 | 125 | /** 126 | * Atomically sets the value to the given updated value 127 | * if the current value {@code ==} the expected value. 128 | * 129 | * @param expect the expected value 130 | * @param update the new value 131 | * @return true if successful. False return indicates that 132 | * the actual value was not equal to the expected value. 133 | */ 134 | public final boolean compareAndSet(int expect, int update) { 135 | return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 136 | } 137 | 138 | /** 139 | * Atomically sets the value to the given updated value 140 | * if the current value {@code ==} the expected value. 141 | * 142 | *

May fail spuriously 143 | * and does not provide ordering guarantees, so is only rarely an 144 | * appropriate alternative to {@code compareAndSet}. 145 | * 146 | * @param expect the expected value 147 | * @param update the new value 148 | * @return true if successful. 149 | */ 150 | public final boolean weakCompareAndSet(int expect, int update) { 151 | return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 152 | } 153 | 154 | /** 155 | * Atomically increments by one the current value. 156 | * 157 | * @return the previous value 158 | */ 159 | public final int getAndIncrement() { 160 | for (;;) { 161 | int current = get(); 162 | int next = current + 1; 163 | if (compareAndSet(current, next)) 164 | return current; 165 | } 166 | } 167 | 168 | /** 169 | * Atomically decrements by one the current value. 170 | * 171 | * @return the previous value 172 | */ 173 | public final int getAndDecrement() { 174 | for (;;) { 175 | int current = get(); 176 | int next = current - 1; 177 | if (compareAndSet(current, next)) 178 | return current; 179 | } 180 | } 181 | 182 | /** 183 | * Atomically adds the given value to the current value. 184 | * 185 | * @param delta the value to add 186 | * @return the previous value 187 | */ 188 | public final int getAndAdd(int delta) { 189 | for (;;) { 190 | int current = get(); 191 | int next = current + delta; 192 | if (compareAndSet(current, next)) 193 | return current; 194 | } 195 | } 196 | 197 | /** 198 | * Atomically increments by one the current value. 199 | * 200 | * @return the updated value 201 | */ 202 | public final int incrementAndGet() { 203 | for (;;) { 204 | int current = get(); 205 | int next = current + 1; 206 | if (compareAndSet(current, next)) 207 | return next; 208 | } 209 | } 210 | 211 | /** 212 | * Atomically decrements by one the current value. 213 | * 214 | * @return the updated value 215 | */ 216 | public final int decrementAndGet() { 217 | for (;;) { 218 | int current = get(); 219 | int next = current - 1; 220 | if (compareAndSet(current, next)) 221 | return next; 222 | } 223 | } 224 | 225 | /** 226 | * Atomically adds the given value to the current value. 227 | * 228 | * @param delta the value to add 229 | * @return the updated value 230 | */ 231 | public final int addAndGet(int delta) { 232 | for (;;) { 233 | int current = get(); 234 | int next = current + delta; 235 | if (compareAndSet(current, next)) 236 | return next; 237 | } 238 | } 239 | 240 | /** 241 | * Returns the String representation of the current value. 242 | * @return the String representation of the current value. 243 | */ 244 | public String toString() { 245 | return Integer.toString(get()); 246 | } 247 | 248 | 249 | public int intValue() { 250 | return get(); 251 | } 252 | 253 | public long longValue() { 254 | return (long)get(); 255 | } 256 | 257 | public float floatValue() { 258 | return (float)get(); 259 | } 260 | 261 | public double doubleValue() { 262 | return (double)get(); 263 | } 264 | 265 | } 266 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicStampedReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | 38 | /** 39 | * An {@code AtomicStampedReference} maintains an object reference 40 | * along with an integer "stamp", that can be updated atomically. 41 | * 42 | *

Implementation note: This implementation maintains stamped 43 | * references by creating internal objects representing "boxed" 44 | * [reference, integer] pairs. 45 | * 46 | * @since 1.5 47 | * @author Doug Lea 48 | * @param The type of object referred to by this reference 49 | */ 50 | public class AtomicStampedReference { 51 | 52 | private static class Pair { 53 | //注意 以下两种成员变量修饰为final 54 | final T reference; 55 | final int stamp; 56 | private Pair(T reference, int stamp) { 57 | this.reference = reference; 58 | this.stamp = stamp; 59 | } 60 | static Pair of(T reference, int stamp) { 61 | return new Pair(reference, stamp); 62 | } 63 | } 64 | //注意 pair修饰为volatile 65 | private volatile Pair pair; 66 | 67 | /** 68 | * Creates a new {@code AtomicStampedReference} with the given 69 | * initial values. 70 | * 71 | * @param initialRef the initial reference 72 | * @param initialStamp the initial stamp 73 | */ 74 | public AtomicStampedReference(V initialRef, int initialStamp) { 75 | pair = Pair.of(initialRef, initialStamp); 76 | } 77 | 78 | /** 79 | * Returns the current value of the reference. 80 | * 81 | * @return the current value of the reference 82 | */ 83 | public V getReference() { 84 | return pair.reference; 85 | } 86 | 87 | /** 88 | * Returns the current value of the stamp. 89 | * 90 | * @return the current value of the stamp 91 | */ 92 | public int getStamp() { 93 | return pair.stamp; 94 | } 95 | 96 | /** 97 | * Returns the current values of both the reference and the stamp. 98 | * Typical usage is {@code int[1] holder; ref = v.get(holder); }. 99 | * 100 | * @param stampHolder an array of size of at least one. On return, 101 | * {@code stampholder[0]} will hold the value of the stamp. 102 | * @return the current value of the reference 103 | */ 104 | public V get(int[] stampHolder) { 105 | Pair pair = this.pair; 106 | stampHolder[0] = pair.stamp; 107 | return pair.reference; 108 | } 109 | 110 | /** 111 | * Atomically sets the value of both the reference and stamp 112 | * to the given update values if the 113 | * current reference is {@code ==} to the expected reference 114 | * and the current stamp is equal to the expected stamp. 115 | * 116 | *

May fail spuriously 117 | * and does not provide ordering guarantees, so is only rarely an 118 | * appropriate alternative to {@code compareAndSet}. 119 | * 120 | * @param expectedReference the expected value of the reference 121 | * @param newReference the new value for the reference 122 | * @param expectedStamp the expected value of the stamp 123 | * @param newStamp the new value for the stamp 124 | * @return true if successful 125 | */ 126 | public boolean weakCompareAndSet(V expectedReference, 127 | V newReference, 128 | int expectedStamp, 129 | int newStamp) { 130 | return compareAndSet(expectedReference, newReference, 131 | expectedStamp, newStamp); 132 | } 133 | 134 | /** 135 | * Atomically sets the value of both the reference and stamp 136 | * to the given update values if the 137 | * current reference is {@code ==} to the expected reference 138 | * and the current stamp is equal to the expected stamp. 139 | * 140 | * @param expectedReference the expected value of the reference 141 | * @param newReference the new value for the reference 142 | * @param expectedStamp the expected value of the stamp 143 | * @param newStamp the new value for the stamp 144 | * @return true if successful 145 | */ 146 | public boolean compareAndSet(V expectedReference, 147 | V newReference, 148 | int expectedStamp, 149 | int newStamp) { 150 | Pair current = pair; 151 | return 152 | expectedReference == current.reference && 153 | expectedStamp == current.stamp && 154 | ((newReference == current.reference && 155 | newStamp == current.stamp) || 156 | casPair(current, Pair.of(newReference, newStamp))); 157 | } 158 | 159 | 160 | /** 161 | * Unconditionally sets the value of both the reference and stamp. 162 | * 163 | * @param newReference the new value for the reference 164 | * @param newStamp the new value for the stamp 165 | */ 166 | public void set(V newReference, int newStamp) { 167 | Pair current = pair; 168 | if (newReference != current.reference || newStamp != current.stamp) 169 | this.pair = Pair.of(newReference, newStamp); 170 | } 171 | 172 | /** 173 | * Atomically sets the value of the stamp to the given update value 174 | * if the current reference is {@code ==} to the expected 175 | * reference. Any given invocation of this operation may fail 176 | * (return {@code false}) spuriously, but repeated invocation 177 | * when the current value holds the expected value and no other 178 | * thread is also attempting to set the value will eventually 179 | * succeed. 180 | * 181 | * @param expectedReference the expected value of the reference 182 | * @param newStamp the new value for the stamp 183 | * @return true if successful 184 | */ 185 | public boolean attemptStamp(V expectedReference, int newStamp) { 186 | Pair current = pair; 187 | return 188 | expectedReference == current.reference && 189 | (newStamp == current.stamp || 190 | casPair(current, Pair.of(expectedReference, newStamp))); 191 | } 192 | 193 | // Unsafe mechanics 194 | 195 | private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); 196 | private static final long pairOffset = 197 | objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class); 198 | 199 | private boolean casPair(Pair cmp, Pair val) { 200 | return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); 201 | } 202 | 203 | static long objectFieldOffset(sun.misc.Unsafe UNSAFE, 204 | String field, Class klazz) { 205 | try { 206 | return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); 207 | } catch (NoSuchFieldException e) { 208 | // Convert Exception to corresponding Error 209 | NoSuchFieldError error = new NoSuchFieldError(field); 210 | error.initCause(e); 211 | throw error; 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicMarkableReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | 38 | /** 39 | * An {@code AtomicMarkableReference} maintains an object reference 40 | * along with a mark bit, that can be updated atomically. 41 | * 42 | *

Implementation note: This implementation maintains markable 43 | * references by creating internal objects representing "boxed" 44 | * [reference, boolean] pairs. 45 | * 46 | * @since 1.5 47 | * @author Doug Lea 48 | * @param The type of object referred to by this reference 49 | */ 50 | public class AtomicMarkableReference { 51 | 52 | private static class Pair { 53 | //注意 以下两个成员变量的类型修饰为final 54 | final T reference; 55 | final boolean mark; 56 | private Pair(T reference, boolean mark) { 57 | this.reference = reference; 58 | this.mark = mark; 59 | } 60 | static Pair of(T reference, boolean mark) { 61 | return new Pair(reference, mark); 62 | } 63 | } 64 | //注意 pair类型修饰为volatile 65 | private volatile Pair pair; 66 | 67 | /** 68 | * Creates a new {@code AtomicMarkableReference} with the given 69 | * initial values. 70 | * 71 | * @param initialRef the initial reference 72 | * @param initialMark the initial mark 73 | */ 74 | public AtomicMarkableReference(V initialRef, boolean initialMark) { 75 | pair = Pair.of(initialRef, initialMark); 76 | } 77 | 78 | /** 79 | * Returns the current value of the reference. 80 | * 81 | * @return the current value of the reference 82 | */ 83 | public V getReference() { 84 | return pair.reference; 85 | } 86 | 87 | /** 88 | * Returns the current value of the mark. 89 | * 90 | * @return the current value of the mark 91 | */ 92 | public boolean isMarked() { 93 | return pair.mark; 94 | } 95 | 96 | /** 97 | * Returns the current values of both the reference and the mark. 98 | * Typical usage is {@code boolean[1] holder; ref = v.get(holder); }. 99 | * 100 | * @param markHolder an array of size of at least one. On return, 101 | * {@code markholder[0]} will hold the value of the mark. 102 | * @return the current value of the reference 103 | */ 104 | public V get(boolean[] markHolder) { 105 | //缓存了一份pair 106 | Pair pair = this.pair; 107 | markHolder[0] = pair.mark; 108 | return pair.reference; 109 | } 110 | 111 | /** 112 | * Atomically sets the value of both the reference and mark 113 | * to the given update values if the 114 | * current reference is {@code ==} to the expected reference 115 | * and the current mark is equal to the expected mark. 116 | * 117 | *

May fail spuriously 118 | * and does not provide ordering guarantees, so is only rarely an 119 | * appropriate alternative to {@code compareAndSet}. 120 | * 121 | * @param expectedReference the expected value of the reference 122 | * @param newReference the new value for the reference 123 | * @param expectedMark the expected value of the mark 124 | * @param newMark the new value for the mark 125 | * @return true if successful 126 | */ 127 | public boolean weakCompareAndSet(V expectedReference, 128 | V newReference, 129 | boolean expectedMark, 130 | boolean newMark) { 131 | return compareAndSet(expectedReference, newReference, 132 | expectedMark, newMark); 133 | } 134 | 135 | /** 136 | * Atomically sets the value of both the reference and mark 137 | * to the given update values if the 138 | * current reference is {@code ==} to the expected reference 139 | * and the current mark is equal to the expected mark. 140 | * 141 | * @param expectedReference the expected value of the reference 142 | * @param newReference the new value for the reference 143 | * @param expectedMark the expected value of the mark 144 | * @param newMark the new value for the mark 145 | * @return true if successful 146 | */ 147 | public boolean compareAndSet(V expectedReference, 148 | V newReference, 149 | boolean expectedMark, 150 | boolean newMark) { 151 | //缓存了一份pair 152 | Pair current = pair; 153 | return //前面几个判断是为了尽量避免cas,同时表明了这一个【时刻(缓存)】不需要进行cas,因为cas前后完全一致 154 | expectedReference == current.reference && 155 | expectedMark == current.mark && 156 | ((newReference == current.reference && 157 | newMark == current.mark) || 158 | casPair(current, Pair.of(newReference, newMark))); 159 | } 160 | 161 | /** 162 | * Unconditionally sets the value of both the reference and mark. 163 | * 164 | * @param newReference the new value for the reference 165 | * @param newMark the new value for the mark 166 | */ 167 | public void set(V newReference, boolean newMark) { 168 | Pair current = pair; 169 | if (newReference != current.reference || newMark != current.mark) 170 | this.pair = Pair.of(newReference, newMark); 171 | } 172 | 173 | /** 174 | * Atomically sets the value of the mark to the given update value 175 | * if the current reference is {@code ==} to the expected 176 | * reference. Any given invocation of this operation may fail 177 | * (return {@code false}) spuriously, but repeated invocation 178 | * when the current value holds the expected value and no other 179 | * thread is also attempting to set the value will eventually 180 | * succeed. 181 | * 182 | * @param expectedReference the expected value of the reference 183 | * @param newMark the new value for the mark 184 | * @return true if successful 185 | */ 186 | public boolean attemptMark(V expectedReference, boolean newMark) { 187 | Pair current = pair; 188 | return 189 | expectedReference == current.reference && 190 | (newMark == current.mark || 191 | casPair(current, Pair.of(expectedReference, newMark))); 192 | } 193 | 194 | // Unsafe mechanics 195 | 196 | private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); 197 | private static final long pairOffset = 198 | objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class); 199 | 200 | private boolean casPair(Pair cmp, Pair val) { 201 | return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); 202 | } 203 | 204 | static long objectFieldOffset(sun.misc.Unsafe UNSAFE, 205 | String field, Class klazz) { 206 | try { 207 | return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); 208 | } catch (NoSuchFieldException e) { 209 | // Convert Exception to corresponding Error 210 | NoSuchFieldError error = new NoSuchFieldError(field); 211 | error.initCause(e); 212 | throw error; 213 | } 214 | } 215 | } -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicLong.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | 39 | /** 40 | * A {@code long} value that may be updated atomically. See the 41 | * {@link java.util.concurrent.atomic} package specification for 42 | * description of the properties of atomic variables. An 43 | * {@code AtomicLong} is used in applications such as atomically 44 | * incremented sequence numbers, and cannot be used as a replacement 45 | * for a {@link java.lang.Long}. However, this class does extend 46 | * {@code Number} to allow uniform access by tools and utilities that 47 | * deal with numerically-based classes. 48 | * 49 | * @since 1.5 50 | * @author Doug Lea 51 | */ 52 | public class AtomicLong extends Number implements java.io.Serializable { 53 | private static final long serialVersionUID = 1927816293512124184L; 54 | 55 | // setup to use Unsafe.compareAndSwapLong for updates 56 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 57 | private static final long valueOffset; 58 | 59 | /** 60 | * Records whether the underlying JVM supports lockless 61 | * compareAndSwap for longs. While the Unsafe.compareAndSwapLong 62 | * method works in either case, some constructions should be 63 | * handled at Java level to avoid locking user-visible locks. 64 | */ 65 | static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); 66 | 67 | /** 68 | * Returns whether underlying JVM supports lockless CompareAndSet 69 | * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS. 70 | */ 71 | private static native boolean VMSupportsCS8(); 72 | 73 | static { 74 | try { 75 | valueOffset = unsafe.objectFieldOffset 76 | (AtomicLong.class.getDeclaredField("value")); 77 | } catch (Exception ex) { throw new Error(ex); } 78 | } 79 | 80 | private volatile long value; 81 | 82 | /** 83 | * Creates a new AtomicLong with the given initial value. 84 | * 85 | * @param initialValue the initial value 86 | */ 87 | public AtomicLong(long initialValue) { 88 | value = initialValue; 89 | } 90 | 91 | /** 92 | * Creates a new AtomicLong with initial value {@code 0}. 93 | */ 94 | public AtomicLong() { 95 | } 96 | 97 | /** 98 | * Gets the current value. 99 | * 100 | * @return the current value 101 | */ 102 | public final long get() { 103 | return value; 104 | } 105 | 106 | /** 107 | * Sets to the given value. 108 | * 109 | * @param newValue the new value 110 | */ 111 | public final void set(long newValue) { 112 | value = newValue; 113 | } 114 | 115 | /** 116 | * Eventually sets to the given value. 117 | * 118 | * @param newValue the new value 119 | * @since 1.6 120 | */ 121 | public final void lazySet(long newValue) { 122 | unsafe.putOrderedLong(this, valueOffset, newValue); 123 | } 124 | 125 | /** 126 | * Atomically sets to the given value and returns the old value. 127 | * 128 | * @param newValue the new value 129 | * @return the previous value 130 | */ 131 | public final long getAndSet(long newValue) { 132 | while (true) { 133 | long current = get(); 134 | if (compareAndSet(current, newValue)) 135 | return current; 136 | } 137 | } 138 | 139 | /** 140 | * Atomically sets the value to the given updated value 141 | * if the current value {@code ==} the expected value. 142 | * 143 | * @param expect the expected value 144 | * @param update the new value 145 | * @return true if successful. False return indicates that 146 | * the actual value was not equal to the expected value. 147 | */ 148 | public final boolean compareAndSet(long expect, long update) { 149 | return unsafe.compareAndSwapLong(this, valueOffset, expect, update); 150 | } 151 | 152 | /** 153 | * Atomically sets the value to the given updated value 154 | * if the current value {@code ==} the expected value. 155 | * 156 | *

May fail spuriously 157 | * and does not provide ordering guarantees, so is only rarely an 158 | * appropriate alternative to {@code compareAndSet}. 159 | * 160 | * @param expect the expected value 161 | * @param update the new value 162 | * @return true if successful. 163 | */ 164 | public final boolean weakCompareAndSet(long expect, long update) { 165 | return unsafe.compareAndSwapLong(this, valueOffset, expect, update); 166 | } 167 | 168 | /** 169 | * Atomically increments by one the current value. 170 | * 171 | * @return the previous value 172 | */ 173 | public final long getAndIncrement() { 174 | while (true) { 175 | long current = get(); 176 | long next = current + 1; 177 | if (compareAndSet(current, next)) 178 | return current; 179 | } 180 | } 181 | 182 | /** 183 | * Atomically decrements by one the current value. 184 | * 185 | * @return the previous value 186 | */ 187 | public final long getAndDecrement() { 188 | while (true) { 189 | long current = get(); 190 | long next = current - 1; 191 | if (compareAndSet(current, next)) 192 | return current; 193 | } 194 | } 195 | 196 | /** 197 | * Atomically adds the given value to the current value. 198 | * 199 | * @param delta the value to add 200 | * @return the previous value 201 | */ 202 | public final long getAndAdd(long delta) { 203 | while (true) { 204 | long current = get(); 205 | long next = current + delta; 206 | if (compareAndSet(current, next)) 207 | return current; 208 | } 209 | } 210 | 211 | /** 212 | * Atomically increments by one the current value. 213 | * 214 | * @return the updated value 215 | */ 216 | public final long incrementAndGet() { 217 | for (;;) { 218 | long current = get(); 219 | long next = current + 1; 220 | if (compareAndSet(current, next)) 221 | return next; 222 | } 223 | } 224 | 225 | /** 226 | * Atomically decrements by one the current value. 227 | * 228 | * @return the updated value 229 | */ 230 | public final long decrementAndGet() { 231 | for (;;) { 232 | long current = get(); 233 | long next = current - 1; 234 | if (compareAndSet(current, next)) 235 | return next; 236 | } 237 | } 238 | 239 | /** 240 | * Atomically adds the given value to the current value. 241 | * 242 | * @param delta the value to add 243 | * @return the updated value 244 | */ 245 | public final long addAndGet(long delta) { 246 | for (;;) { 247 | long current = get(); 248 | long next = current + delta; 249 | if (compareAndSet(current, next)) 250 | return next; 251 | } 252 | } 253 | 254 | /** 255 | * Returns the String representation of the current value. 256 | * @return the String representation of the current value. 257 | */ 258 | public String toString() { 259 | return Long.toString(get()); 260 | } 261 | 262 | 263 | public int intValue() { 264 | return (int)get(); 265 | } 266 | 267 | public long longValue() { 268 | return get(); 269 | } 270 | 271 | public float floatValue() { 272 | return (float)get(); 273 | } 274 | 275 | public double doubleValue() { 276 | return (double)get(); 277 | } 278 | 279 | } 280 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/park.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 | * or visit www.oracle.com if you need additional information or have any 21 | * questions. 22 | * 23 | */ 24 | 25 | #include "precompiled.hpp" 26 | #include "runtime/thread.hpp" 27 | 28 | 29 | 30 | // Lifecycle management for TSM ParkEvents. 31 | // ParkEvents are type-stable (TSM). 32 | // In our particular implementation they happen to be immortal. 33 | // 34 | // We manage concurrency on the FreeList with a CAS-based 35 | // detach-modify-reattach idiom that avoids the ABA problems 36 | // that would otherwise be present in a simple CAS-based 37 | // push-pop implementation. (push-one and pop-all) 38 | // 39 | // Caveat: Allocate() and Release() may be called from threads 40 | // other than the thread associated with the Event! 41 | // If we need to call Allocate() when running as the thread in 42 | // question then look for the PD calls to initialize native TLS. 43 | // Native TLS (Win32/Linux/Solaris) can only be initialized or 44 | // accessed by the associated thread. 45 | // See also pd_initialize(). 46 | // 47 | // Note that we could defer associating a ParkEvent with a thread 48 | // until the 1st time the thread calls park(). unpark() calls to 49 | // an unprovisioned thread would be ignored. The first park() call 50 | // for a thread would allocate and associate a ParkEvent and return 51 | // immediately. 52 | 53 | volatile int ParkEvent::ListLock = 0 ; 54 | ParkEvent * volatile ParkEvent::FreeList = NULL ; 55 | 56 | ParkEvent * ParkEvent::Allocate (Thread * t) { 57 | // In rare cases -- JVM_RawMonitor* operations -- we can find t == null. 58 | ParkEvent * ev ; 59 | 60 | // Start by trying to recycle an existing but unassociated 61 | // ParkEvent from the global free list. 62 | for (;;) { 63 | ev = FreeList ; 64 | if (ev == NULL) break ; 65 | // 1: Detach - sequester or privatize the list 66 | // Tantamount to ev = Swap (&FreeList, NULL) 67 | if (Atomic::cmpxchg_ptr (NULL, &FreeList, ev) != ev) { 68 | continue ; 69 | } 70 | 71 | // We've detached the list. The list in-hand is now 72 | // local to this thread. This thread can operate on the 73 | // list without risk of interference from other threads. 74 | // 2: Extract -- pop the 1st element from the list. 75 | ParkEvent * List = ev->FreeNext ; 76 | if (List == NULL) break ; 77 | for (;;) { 78 | // 3: Try to reattach the residual list 79 | guarantee (List != NULL, "invariant") ; 80 | ParkEvent * Arv = (ParkEvent *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ; 81 | if (Arv == NULL) break ; 82 | 83 | // New nodes arrived. Try to detach the recent arrivals. 84 | if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) { 85 | continue ; 86 | } 87 | guarantee (Arv != NULL, "invariant") ; 88 | // 4: Merge Arv into List 89 | ParkEvent * Tail = List ; 90 | while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ; 91 | Tail->FreeNext = Arv ; 92 | } 93 | break ; 94 | } 95 | 96 | if (ev != NULL) { 97 | guarantee (ev->AssociatedWith == NULL, "invariant") ; 98 | } else { 99 | // Do this the hard way -- materialize a new ParkEvent. 100 | // In rare cases an allocating thread might detach a long list -- 101 | // installing null into FreeList -- and then stall or be obstructed. 102 | // A 2nd thread calling Allocate() would see FreeList == null. 103 | // The list held privately by the 1st thread is unavailable to the 2nd thread. 104 | // In that case the 2nd thread would have to materialize a new ParkEvent, 105 | // even though free ParkEvents existed in the system. In this case we end up 106 | // with more ParkEvents in circulation than we need, but the race is 107 | // rare and the outcome is benign. Ideally, the # of extant ParkEvents 108 | // is equal to the maximum # of threads that existed at any one time. 109 | // Because of the race mentioned above, segments of the freelist 110 | // can be transiently inaccessible. At worst we may end up with the 111 | // # of ParkEvents in circulation slightly above the ideal. 112 | // Note that if we didn't have the TSM/immortal constraint, then 113 | // when reattaching, above, we could trim the list. 114 | ev = new ParkEvent () ; 115 | guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ; 116 | } 117 | ev->reset() ; // courtesy to caller 118 | ev->AssociatedWith = t ; // Associate ev with t 119 | ev->FreeNext = NULL ; 120 | return ev ; 121 | } 122 | 123 | void ParkEvent::Release (ParkEvent * ev) { 124 | if (ev == NULL) return ; 125 | guarantee (ev->FreeNext == NULL , "invariant") ; 126 | ev->AssociatedWith = NULL ; 127 | for (;;) { 128 | // Push ev onto FreeList 129 | // The mechanism is "half" lock-free. 130 | ParkEvent * List = FreeList ; 131 | ev->FreeNext = List ; 132 | if (Atomic::cmpxchg_ptr (ev, &FreeList, List) == List) break ; 133 | } 134 | } 135 | 136 | // Override operator new and delete so we can ensure that the 137 | // least significant byte of ParkEvent addresses is 0. 138 | // Beware that excessive address alignment is undesirable 139 | // as it can result in D$ index usage imbalance as 140 | // well as bank access imbalance on Niagara-like platforms, 141 | // although Niagara's hash function should help. 142 | 143 | void * ParkEvent::operator new (size_t sz) { 144 | return (void *) ((intptr_t (CHeapObj::operator new (sz + 256)) + 256) & -256) ; 145 | } 146 | 147 | void ParkEvent::operator delete (void * a) { 148 | // ParkEvents are type-stable and immortal ... 149 | ShouldNotReachHere(); 150 | } 151 | 152 | 153 | // 6399321 As a temporary measure we copied & modified the ParkEvent:: 154 | // allocate() and release() code for use by Parkers. The Parker:: forms 155 | // will eventually be removed as we consolide and shift over to ParkEvents 156 | // for both builtin synchronization and JSR166 operations. 157 | 158 | volatile int Parker::ListLock = 0 ; 159 | Parker * volatile Parker::FreeList = NULL ; 160 | 161 | Parker * Parker::Allocate (JavaThread * t) { 162 | guarantee (t != NULL, "invariant") ; 163 | Parker * p ; 164 | 165 | // Start by trying to recycle an existing but unassociated 166 | // Parker from the global free list. 167 | for (;;) { 168 | p = FreeList ; 169 | if (p == NULL) break ; 170 | // 1: Detach 171 | // Tantamount to p = Swap (&FreeList, NULL) 172 | if (Atomic::cmpxchg_ptr (NULL, &FreeList, p) != p) { 173 | continue ; 174 | } 175 | 176 | // We've detached the list. The list in-hand is now 177 | // local to this thread. This thread can operate on the 178 | // list without risk of interference from other threads. 179 | // 2: Extract -- pop the 1st element from the list. 180 | Parker * List = p->FreeNext ; 181 | if (List == NULL) break ; 182 | for (;;) { 183 | // 3: Try to reattach the residual list 184 | guarantee (List != NULL, "invariant") ; 185 | Parker * Arv = (Parker *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ; 186 | if (Arv == NULL) break ; 187 | 188 | // New nodes arrived. Try to detach the recent arrivals. 189 | if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) { 190 | continue ; 191 | } 192 | guarantee (Arv != NULL, "invariant") ; 193 | // 4: Merge Arv into List 194 | Parker * Tail = List ; 195 | while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ; 196 | Tail->FreeNext = Arv ; 197 | } 198 | break ; 199 | } 200 | 201 | if (p != NULL) { 202 | guarantee (p->AssociatedWith == NULL, "invariant") ; 203 | } else { 204 | // Do this the hard way -- materialize a new Parker.. 205 | // In rare cases an allocating thread might detach 206 | // a long list -- installing null into FreeList --and 207 | // then stall. Another thread calling Allocate() would see 208 | // FreeList == null and then invoke the ctor. In this case we 209 | // end up with more Parkers in circulation than we need, but 210 | // the race is rare and the outcome is benign. 211 | // Ideally, the # of extant Parkers is equal to the 212 | // maximum # of threads that existed at any one time. 213 | // Because of the race mentioned above, segments of the 214 | // freelist can be transiently inaccessible. At worst 215 | // we may end up with the # of Parkers in circulation 216 | // slightly above the ideal. 217 | p = new Parker() ; 218 | } 219 | p->AssociatedWith = t ; // Associate p with t 220 | p->FreeNext = NULL ; 221 | return p ; 222 | } 223 | 224 | 225 | void Parker::Release (Parker * p) { 226 | if (p == NULL) return ; 227 | guarantee (p->AssociatedWith != NULL, "invariant") ; 228 | guarantee (p->FreeNext == NULL , "invariant") ; 229 | p->AssociatedWith = NULL ; 230 | for (;;) { 231 | // Push p onto FreeList 232 | Parker * List = FreeList ; 233 | p->FreeNext = List ; 234 | if (Atomic::cmpxchg_ptr (p, &FreeList, List) == List) break ; 235 | } 236 | } 237 | 238 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicLongArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | import java.util.*; 39 | 40 | /** 41 | * A {@code long} array in which elements may be updated atomically. 42 | * See the {@link java.util.concurrent.atomic} package specification 43 | * for description of the properties of atomic variables. 44 | * @since 1.5 45 | * @author Doug Lea 46 | */ 47 | public class AtomicLongArray implements java.io.Serializable { 48 | private static final long serialVersionUID = -2308431214976778248L; 49 | 50 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 51 | private static final int base = unsafe.arrayBaseOffset(long[].class); 52 | private static final int shift; 53 | private final long[] array; 54 | 55 | static { 56 | int scale = unsafe.arrayIndexScale(long[].class); 57 | if ((scale & (scale - 1)) != 0) 58 | throw new Error("data type scale not a power of two"); 59 | shift = 31 - Integer.numberOfLeadingZeros(scale); 60 | } 61 | 62 | private long checkedByteOffset(int i) { 63 | if (i < 0 || i >= array.length) 64 | throw new IndexOutOfBoundsException("index " + i); 65 | 66 | return byteOffset(i); 67 | } 68 | 69 | private static long byteOffset(int i) { 70 | return ((long) i << shift) + base; 71 | } 72 | 73 | /** 74 | * Creates a new AtomicLongArray of the given length, with all 75 | * elements initially zero. 76 | * 77 | * @param length the length of the array 78 | */ 79 | public AtomicLongArray(int length) { 80 | array = new long[length]; 81 | } 82 | 83 | /** 84 | * Creates a new AtomicLongArray with the same length as, and 85 | * all elements copied from, the given array. 86 | * 87 | * @param array the array to copy elements from 88 | * @throws NullPointerException if array is null 89 | */ 90 | public AtomicLongArray(long[] array) { 91 | // Visibility guaranteed by final field guarantees 92 | this.array = array.clone(); 93 | } 94 | 95 | /** 96 | * Returns the length of the array. 97 | * 98 | * @return the length of the array 99 | */ 100 | public final int length() { 101 | return array.length; 102 | } 103 | 104 | /** 105 | * Gets the current value at position {@code i}. 106 | * 107 | * @param i the index 108 | * @return the current value 109 | */ 110 | public final long get(int i) { 111 | return getRaw(checkedByteOffset(i)); 112 | } 113 | 114 | private long getRaw(long offset) { 115 | return unsafe.getLongVolatile(array, offset); 116 | } 117 | 118 | /** 119 | * Sets the element at position {@code i} to the given value. 120 | * 121 | * @param i the index 122 | * @param newValue the new value 123 | */ 124 | public final void set(int i, long newValue) { 125 | unsafe.putLongVolatile(array, checkedByteOffset(i), newValue); 126 | } 127 | 128 | /** 129 | * Eventually sets the element at position {@code i} to the given value. 130 | * 131 | * @param i the index 132 | * @param newValue the new value 133 | * @since 1.6 134 | */ 135 | public final void lazySet(int i, long newValue) { 136 | unsafe.putOrderedLong(array, checkedByteOffset(i), newValue); 137 | } 138 | 139 | 140 | /** 141 | * Atomically sets the element at position {@code i} to the given value 142 | * and returns the old value. 143 | * 144 | * @param i the index 145 | * @param newValue the new value 146 | * @return the previous value 147 | */ 148 | public final long getAndSet(int i, long newValue) { 149 | long offset = checkedByteOffset(i); 150 | while (true) { 151 | long current = getRaw(offset); 152 | if (compareAndSetRaw(offset, current, newValue)) 153 | return current; 154 | } 155 | } 156 | 157 | /** 158 | * Atomically sets the element at position {@code i} to the given 159 | * updated value if the current value {@code ==} the expected value. 160 | * 161 | * @param i the index 162 | * @param expect the expected value 163 | * @param update the new value 164 | * @return true if successful. False return indicates that 165 | * the actual value was not equal to the expected value. 166 | */ 167 | public final boolean compareAndSet(int i, long expect, long update) { 168 | return compareAndSetRaw(checkedByteOffset(i), expect, update); 169 | } 170 | 171 | private boolean compareAndSetRaw(long offset, long expect, long update) { 172 | return unsafe.compareAndSwapLong(array, offset, expect, update); 173 | } 174 | 175 | /** 176 | * Atomically sets the element at position {@code i} to the given 177 | * updated value if the current value {@code ==} the expected value. 178 | * 179 | *

May fail spuriously 180 | * and does not provide ordering guarantees, so is only rarely an 181 | * appropriate alternative to {@code compareAndSet}. 182 | * 183 | * @param i the index 184 | * @param expect the expected value 185 | * @param update the new value 186 | * @return true if successful. 187 | */ 188 | public final boolean weakCompareAndSet(int i, long expect, long update) { 189 | return compareAndSet(i, expect, update); 190 | } 191 | 192 | /** 193 | * Atomically increments by one the element at index {@code i}. 194 | * 195 | * @param i the index 196 | * @return the previous value 197 | */ 198 | public final long getAndIncrement(int i) { 199 | return getAndAdd(i, 1); 200 | } 201 | 202 | /** 203 | * Atomically decrements by one the element at index {@code i}. 204 | * 205 | * @param i the index 206 | * @return the previous value 207 | */ 208 | public final long getAndDecrement(int i) { 209 | return getAndAdd(i, -1); 210 | } 211 | 212 | /** 213 | * Atomically adds the given value to the element at index {@code i}. 214 | * 215 | * @param i the index 216 | * @param delta the value to add 217 | * @return the previous value 218 | */ 219 | public final long getAndAdd(int i, long delta) { 220 | long offset = checkedByteOffset(i); 221 | while (true) { 222 | long current = getRaw(offset); 223 | if (compareAndSetRaw(offset, current, current + delta)) 224 | return current; 225 | } 226 | } 227 | 228 | /** 229 | * Atomically increments by one the element at index {@code i}. 230 | * 231 | * @param i the index 232 | * @return the updated value 233 | */ 234 | public final long incrementAndGet(int i) { 235 | return addAndGet(i, 1); 236 | } 237 | 238 | /** 239 | * Atomically decrements by one the element at index {@code i}. 240 | * 241 | * @param i the index 242 | * @return the updated value 243 | */ 244 | public final long decrementAndGet(int i) { 245 | return addAndGet(i, -1); 246 | } 247 | 248 | /** 249 | * Atomically adds the given value to the element at index {@code i}. 250 | * 251 | * @param i the index 252 | * @param delta the value to add 253 | * @return the updated value 254 | */ 255 | public long addAndGet(int i, long delta) { 256 | long offset = checkedByteOffset(i); 257 | while (true) { 258 | long current = getRaw(offset); 259 | long next = current + delta; 260 | if (compareAndSetRaw(offset, current, next)) 261 | return next; 262 | } 263 | } 264 | 265 | /** 266 | * Returns the String representation of the current values of array. 267 | * @return the String representation of the current values of array 268 | */ 269 | public String toString() { 270 | int iMax = array.length - 1; 271 | if (iMax == -1) 272 | return "[]"; 273 | 274 | StringBuilder b = new StringBuilder(); 275 | b.append('['); 276 | for (int i = 0; ; i++) { 277 | b.append(getRaw(byteOffset(i))); 278 | if (i == iMax) 279 | return b.append(']').toString(); 280 | b.append(',').append(' '); 281 | } 282 | } 283 | 284 | } 285 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicIntegerArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | import java.util.*; 39 | 40 | /** 41 | * An {@code int} array in which elements may be updated atomically. 42 | * See the {@link java.util.concurrent.atomic} package 43 | * specification for description of the properties of atomic 44 | * variables. 45 | * @since 1.5 46 | * @author Doug Lea 47 | */ 48 | public class AtomicIntegerArray implements java.io.Serializable { 49 | private static final long serialVersionUID = 2862133569453604235L; 50 | 51 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 52 | private static final int base = unsafe.arrayBaseOffset(int[].class); 53 | private static final int shift; 54 | private final int[] array; 55 | 56 | static { 57 | int scale = unsafe.arrayIndexScale(int[].class); 58 | if ((scale & (scale - 1)) != 0) 59 | throw new Error("data type scale not a power of two"); 60 | //Integer.numberOfLeadingZeros返回数据的二进制串中从最左边算起连续的“0”的总数量。 61 | shift = 31 - Integer.numberOfLeadingZeros(scale); 62 | } 63 | 64 | private long checkedByteOffset(int i) { 65 | if (i < 0 || i >= array.length) 66 | throw new IndexOutOfBoundsException("index " + i); 67 | 68 | return byteOffset(i); 69 | } 70 | 71 | private static long byteOffset(int i) { 72 | return ((long) i << shift) + base; 73 | } 74 | 75 | /** 76 | * Creates a new AtomicIntegerArray of the given length, with all 77 | * elements initially zero. 78 | * 79 | * @param length the length of the array 80 | */ 81 | public AtomicIntegerArray(int length) { 82 | array = new int[length]; 83 | } 84 | 85 | /** 86 | * Creates a new AtomicIntegerArray with the same length as, and 87 | * all elements copied from, the given array. 88 | * 89 | * @param array the array to copy elements from 90 | * @throws NullPointerException if array is null 91 | */ 92 | public AtomicIntegerArray(int[] array) { 93 | // Visibility guaranteed by final field guarantees 94 | this.array = array.clone(); 95 | } 96 | 97 | /** 98 | * Returns the length of the array. 99 | * 100 | * @return the length of the array 101 | */ 102 | public final int length() { 103 | return array.length; 104 | } 105 | 106 | /** 107 | * Gets the current value at position {@code i}. 108 | * 109 | * @param i the index 110 | * @return the current value 111 | */ 112 | public final int get(int i) { 113 | return getRaw(checkedByteOffset(i)); 114 | } 115 | 116 | private int getRaw(long offset) { 117 | return unsafe.getIntVolatile(array, offset); 118 | } 119 | 120 | /** 121 | * Sets the element at position {@code i} to the given value. 122 | * 123 | * @param i the index 124 | * @param newValue the new value 125 | */ 126 | public final void set(int i, int newValue) { 127 | unsafe.putIntVolatile(array, checkedByteOffset(i), newValue); 128 | } 129 | 130 | /** 131 | * Eventually sets the element at position {@code i} to the given value. 132 | * 133 | * @param i the index 134 | * @param newValue the new value 135 | * @since 1.6 136 | */ 137 | public final void lazySet(int i, int newValue) { 138 | unsafe.putOrderedInt(array, checkedByteOffset(i), newValue); 139 | } 140 | 141 | /** 142 | * Atomically sets the element at position {@code i} to the given 143 | * value and returns the old value. 144 | * 145 | * @param i the index 146 | * @param newValue the new value 147 | * @return the previous value 148 | */ 149 | public final int getAndSet(int i, int newValue) { 150 | long offset = checkedByteOffset(i); 151 | while (true) { 152 | int current = getRaw(offset); 153 | if (compareAndSetRaw(offset, current, newValue)) 154 | return current; 155 | } 156 | } 157 | 158 | /** 159 | * Atomically sets the element at position {@code i} to the given 160 | * updated value if the current value {@code ==} the expected value. 161 | * 162 | * @param i the index 163 | * @param expect the expected value 164 | * @param update the new value 165 | * @return true if successful. False return indicates that 166 | * the actual value was not equal to the expected value. 167 | */ 168 | public final boolean compareAndSet(int i, int expect, int update) { 169 | return compareAndSetRaw(checkedByteOffset(i), expect, update); 170 | } 171 | 172 | private boolean compareAndSetRaw(long offset, int expect, int update) { 173 | return unsafe.compareAndSwapInt(array, offset, expect, update); 174 | } 175 | 176 | /** 177 | * Atomically sets the element at position {@code i} to the given 178 | * updated value if the current value {@code ==} the expected value. 179 | * 180 | *

May fail spuriously 181 | * and does not provide ordering guarantees, so is only rarely an 182 | * appropriate alternative to {@code compareAndSet}. 183 | * 184 | * @param i the index 185 | * @param expect the expected value 186 | * @param update the new value 187 | * @return true if successful. 188 | */ 189 | public final boolean weakCompareAndSet(int i, int expect, int update) { 190 | return compareAndSet(i, expect, update); 191 | } 192 | 193 | /** 194 | * Atomically increments by one the element at index {@code i}. 195 | * 196 | * @param i the index 197 | * @return the previous value 198 | */ 199 | public final int getAndIncrement(int i) { 200 | return getAndAdd(i, 1); 201 | } 202 | 203 | /** 204 | * Atomically decrements by one the element at index {@code i}. 205 | * 206 | * @param i the index 207 | * @return the previous value 208 | */ 209 | public final int getAndDecrement(int i) { 210 | return getAndAdd(i, -1); 211 | } 212 | 213 | /** 214 | * Atomically adds the given value to the element at index {@code i}. 215 | * 216 | * @param i the index 217 | * @param delta the value to add 218 | * @return the previous value 219 | */ 220 | public final int getAndAdd(int i, int delta) { 221 | long offset = checkedByteOffset(i); 222 | while (true) { 223 | int current = getRaw(offset); 224 | if (compareAndSetRaw(offset, current, current + delta)) 225 | return current; 226 | } 227 | } 228 | 229 | /** 230 | * Atomically increments by one the element at index {@code i}. 231 | * 232 | * @param i the index 233 | * @return the updated value 234 | */ 235 | public final int incrementAndGet(int i) { 236 | return addAndGet(i, 1); 237 | } 238 | 239 | /** 240 | * Atomically decrements by one the element at index {@code i}. 241 | * 242 | * @param i the index 243 | * @return the updated value 244 | */ 245 | public final int decrementAndGet(int i) { 246 | return addAndGet(i, -1); 247 | } 248 | 249 | /** 250 | * Atomically adds the given value to the element at index {@code i}. 251 | * 252 | * @param i the index 253 | * @param delta the value to add 254 | * @return the updated value 255 | */ 256 | public final int addAndGet(int i, int delta) { 257 | long offset = checkedByteOffset(i); 258 | while (true) { 259 | int current = getRaw(offset); 260 | int next = current + delta; 261 | if (compareAndSetRaw(offset, current, next)) 262 | return next; 263 | } 264 | } 265 | 266 | /** 267 | * Returns the String representation of the current values of array. 268 | * @return the String representation of the current values of array 269 | */ 270 | public String toString() { 271 | int iMax = array.length - 1; 272 | if (iMax == -1) 273 | return "[]"; 274 | 275 | StringBuilder b = new StringBuilder(); 276 | b.append('['); 277 | for (int i = 0; ; i++) { 278 | b.append(getRaw(byteOffset(i))); 279 | if (i == iMax) 280 | return b.append(']').toString(); 281 | b.append(',').append(' '); 282 | } 283 | } 284 | 285 | } 286 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | /** 37 | * A small toolkit of classes that support lock-free thread-safe 38 | * programming on single variables. In essence, the classes in this 39 | * package extend the notion of {@code volatile} values, fields, and 40 | * array elements to those that also provide an atomic conditional update 41 | * operation of the form: 42 | * 43 | *

 44 |  *   boolean compareAndSet(expectedValue, updateValue);
 45 |  * 
46 | * 47 | *

This method (which varies in argument types across different 48 | * classes) atomically sets a variable to the {@code updateValue} if it 49 | * currently holds the {@code expectedValue}, reporting {@code true} on 50 | * success. The classes in this package also contain methods to get and 51 | * unconditionally set values, as well as a weaker conditional atomic 52 | * update operation {@code weakCompareAndSet} described below. 53 | * 54 | *

The specifications of these methods enable implementations to 55 | * employ efficient machine-level atomic instructions that are available 56 | * on contemporary processors. However on some platforms, support may 57 | * entail some form of internal locking. Thus the methods are not 58 | * strictly guaranteed to be non-blocking -- 59 | * a thread may block transiently before performing the operation. 60 | * 61 | *

Instances of classes 62 | * {@link java.util.concurrent.atomic.AtomicBoolean}, 63 | * {@link java.util.concurrent.atomic.AtomicInteger}, 64 | * {@link java.util.concurrent.atomic.AtomicLong}, and 65 | * {@link java.util.concurrent.atomic.AtomicReference} 66 | * each provide access and updates to a single variable of the 67 | * corresponding type. Each class also provides appropriate utility 68 | * methods for that type. For example, classes {@code AtomicLong} and 69 | * {@code AtomicInteger} provide atomic increment methods. One 70 | * application is to generate sequence numbers, as in: 71 | * 72 | *

 73 |  * class Sequencer {
 74 |  *   private final AtomicLong sequenceNumber
 75 |  *     = new AtomicLong(0);
 76 |  *   public long next() {
 77 |  *     return sequenceNumber.getAndIncrement();
 78 |  *   }
 79 |  * }
 80 |  * 
81 | * 82 | *

The memory effects for accesses and updates of atomics generally 83 | * follow the rules for volatiles, as stated in section 17.4 of 84 | * The Java™ Language Specification. 85 | * 86 | *

113 | * 114 | *

In addition to classes representing single values, this package 115 | * contains Updater classes that can be used to obtain 116 | * {@code compareAndSet} operations on any selected {@code volatile} 117 | * field of any selected class. 118 | * 119 | * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater}, 120 | * {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and 121 | * {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are 122 | * reflection-based utilities that provide access to the associated 123 | * field types. These are mainly of use in atomic data structures in 124 | * which several {@code volatile} fields of the same node (for 125 | * example, the links of a tree node) are independently subject to 126 | * atomic updates. These classes enable greater flexibility in how 127 | * and when to use atomic updates, at the expense of more awkward 128 | * reflection-based setup, less convenient usage, and weaker 129 | * guarantees. 130 | * 131 | *

The 132 | * {@link java.util.concurrent.atomic.AtomicIntegerArray}, 133 | * {@link java.util.concurrent.atomic.AtomicLongArray}, and 134 | * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes 135 | * further extend atomic operation support to arrays of these types. 136 | * These classes are also notable in providing {@code volatile} access 137 | * semantics for their array elements, which is not supported for 138 | * ordinary arrays. 139 | * 140 | * 141 | *

The atomic classes also support method {@code weakCompareAndSet}, 142 | * which has limited applicability. On some platforms, the weak version 143 | * may be more efficient than {@code compareAndSet} in the normal case, 144 | * but differs in that any given invocation of the 145 | * {@code weakCompareAndSet} method may return {@code false} 146 | * spuriously (that is, for no apparent reason). A 147 | * {@code false} return means only that the operation may be retried if 148 | * desired, relying on the guarantee that repeated invocation when the 149 | * variable holds {@code expectedValue} and no other thread is also 150 | * attempting to set the variable will eventually succeed. (Such 151 | * spurious failures may for example be due to memory contention effects 152 | * that are unrelated to whether the expected and current values are 153 | * equal.) Additionally {@code weakCompareAndSet} does not provide 154 | * ordering guarantees that are usually needed for synchronization 155 | * control. However, the method may be useful for updating counters and 156 | * statistics when such updates are unrelated to the other 157 | * happens-before orderings of a program. When a thread sees an update 158 | * to an atomic variable caused by a {@code weakCompareAndSet}, it does 159 | * not necessarily see updates to any other variables that 160 | * occurred before the {@code weakCompareAndSet}. This may be 161 | * acceptable when, for example, updating performance statistics, but 162 | * rarely otherwise. 163 | * 164 | *

The {@link java.util.concurrent.atomic.AtomicMarkableReference} 165 | * class associates a single boolean with a reference. For example, this 166 | * bit might be used inside a data structure to mean that the object 167 | * being referenced has logically been deleted. 168 | * 169 | * The {@link java.util.concurrent.atomic.AtomicStampedReference} 170 | * class associates an integer value with a reference. This may be 171 | * used for example, to represent version numbers corresponding to 172 | * series of updates. 173 | * 174 | *

Atomic classes are designed primarily as building blocks for 175 | * implementing non-blocking data structures and related infrastructure 176 | * classes. The {@code compareAndSet} method is not a general 177 | * replacement for locking. It applies only when critical updates for an 178 | * object are confined to a single variable. 179 | * 180 | *

Atomic classes are not general purpose replacements for 181 | * {@code java.lang.Integer} and related classes. They do not 182 | * define methods such as {@code hashCode} and 183 | * {@code compareTo}. (Because atomic variables are expected to be 184 | * mutated, they are poor choices for hash table keys.) Additionally, 185 | * classes are provided only for those types that are commonly useful in 186 | * intended applications. For example, there is no atomic class for 187 | * representing {@code byte}. In those infrequent cases where you would 188 | * like to do so, you can use an {@code AtomicInteger} to hold 189 | * {@code byte} values, and cast appropriately. 190 | * 191 | * You can also hold floats using 192 | * {@link java.lang.Float#floatToIntBits} and 193 | * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using 194 | * {@link java.lang.Double#doubleToLongBits} and 195 | * {@link java.lang.Double#longBitsToDouble} conversions. 196 | * 197 | * @since 1.5 198 | */ 199 | package java.util.concurrent.atomic; 200 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicReferenceFieldUpdater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | import java.lang.reflect.*; 39 | 40 | /** 41 | * A reflection-based utility that enables atomic updates to 42 | * designated {@code volatile} reference fields of designated 43 | * classes. This class is designed for use in atomic data structures 44 | * in which several reference fields of the same node are 45 | * independently subject to atomic updates. For example, a tree node 46 | * might be declared as 47 | * 48 | *

 {@code
 49 |  * class Node {
 50 |  *   private volatile Node left, right;
 51 |  *
 52 |  *   private static final AtomicReferenceFieldUpdater leftUpdater =
 53 |  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
 54 |  *   private static AtomicReferenceFieldUpdater rightUpdater =
 55 |  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
 56 |  *
 57 |  *   Node getLeft() { return left;  }
 58 |  *   boolean compareAndSetLeft(Node expect, Node update) {
 59 |  *     return leftUpdater.compareAndSet(this, expect, update);
 60 |  *   }
 61 |  *   // ... and so on
 62 |  * }}
63 | * 64 | *

Note that the guarantees of the {@code compareAndSet} 65 | * method in this class are weaker than in other atomic classes. 66 | * Because this class cannot ensure that all uses of the field 67 | * are appropriate for purposes of atomic access, it can 68 | * guarantee atomicity only with respect to other invocations of 69 | * {@code compareAndSet} and {@code set} on the same updater. 70 | * 71 | * @since 1.5 72 | * @author Doug Lea 73 | * @param The type of the object holding the updatable field 74 | * @param The type of the field 75 | */ 76 | public abstract class AtomicReferenceFieldUpdater { 77 | 78 | /** 79 | * Creates and returns an updater for objects with the given field. 80 | * The Class arguments are needed to check that reflective types and 81 | * generic types match. 82 | * 83 | * @param tclass the class of the objects holding the field. 84 | * @param vclass the class of the field 85 | * @param fieldName the name of the field to be updated. 86 | * @return the updater 87 | * @throws IllegalArgumentException if the field is not a volatile reference type. 88 | * @throws RuntimeException with a nested reflection-based 89 | * exception if the class does not hold field or is the wrong type. 90 | */ 91 | public static AtomicReferenceFieldUpdater newUpdater(Class tclass, Class vclass, String fieldName) { 92 | return new AtomicReferenceFieldUpdaterImpl(tclass, 93 | vclass, 94 | fieldName); 95 | } 96 | 97 | /** 98 | * Protected do-nothing constructor for use by subclasses. 99 | */ 100 | protected AtomicReferenceFieldUpdater() { 101 | } 102 | 103 | /** 104 | * Atomically sets the field of the given object managed by this updater 105 | * to the given updated value if the current value {@code ==} the 106 | * expected value. This method is guaranteed to be atomic with respect to 107 | * other calls to {@code compareAndSet} and {@code set}, but not 108 | * necessarily with respect to other changes in the field. 109 | * 110 | * @param obj An object whose field to conditionally set 111 | * @param expect the expected value 112 | * @param update the new value 113 | * @return true if successful. 114 | */ 115 | public abstract boolean compareAndSet(T obj, V expect, V update); 116 | 117 | /** 118 | * Atomically sets the field of the given object managed by this updater 119 | * to the given updated value if the current value {@code ==} the 120 | * expected value. This method is guaranteed to be atomic with respect to 121 | * other calls to {@code compareAndSet} and {@code set}, but not 122 | * necessarily with respect to other changes in the field. 123 | * 124 | *

May fail spuriously 125 | * and does not provide ordering guarantees, so is only rarely an 126 | * appropriate alternative to {@code compareAndSet}. 127 | * 128 | * @param obj An object whose field to conditionally set 129 | * @param expect the expected value 130 | * @param update the new value 131 | * @return true if successful. 132 | */ 133 | public abstract boolean weakCompareAndSet(T obj, V expect, V update); 134 | 135 | /** 136 | * Sets the field of the given object managed by this updater to the 137 | * given updated value. This operation is guaranteed to act as a volatile 138 | * store with respect to subsequent invocations of {@code compareAndSet}. 139 | * 140 | * @param obj An object whose field to set 141 | * @param newValue the new value 142 | */ 143 | public abstract void set(T obj, V newValue); 144 | 145 | /** 146 | * Eventually sets the field of the given object managed by this 147 | * updater to the given updated value. 148 | * 149 | * @param obj An object whose field to set 150 | * @param newValue the new value 151 | * @since 1.6 152 | */ 153 | public abstract void lazySet(T obj, V newValue); 154 | 155 | /** 156 | * Gets the current value held in the field of the given object managed 157 | * by this updater. 158 | * 159 | * @param obj An object whose field to get 160 | * @return the current value 161 | */ 162 | public abstract V get(T obj); 163 | 164 | /** 165 | * Atomically sets the field of the given object managed by this updater 166 | * to the given value and returns the old value. 167 | * 168 | * @param obj An object whose field to get and set 169 | * @param newValue the new value 170 | * @return the previous value 171 | */ 172 | public V getAndSet(T obj, V newValue) { 173 | for (;;) { 174 | V current = get(obj); 175 | if (compareAndSet(obj, current, newValue)) 176 | return current; 177 | } 178 | } 179 | 180 | private static final class AtomicReferenceFieldUpdaterImpl 181 | extends AtomicReferenceFieldUpdater { 182 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 183 | private final long offset; 184 | private final Class tclass; 185 | private final Class vclass; 186 | private final Class cclass; 187 | 188 | /* 189 | * Internal type checks within all update methods contain 190 | * internal inlined optimizations checking for the common 191 | * cases where the class is final (in which case a simple 192 | * getClass comparison suffices) or is of type Object (in 193 | * which case no check is needed because all objects are 194 | * instances of Object). The Object case is handled simply by 195 | * setting vclass to null in constructor. The targetCheck and 196 | * updateCheck methods are invoked when these faster 197 | * screenings fail. 198 | */ 199 | 200 | AtomicReferenceFieldUpdaterImpl(Class tclass, 201 | Class vclass, 202 | String fieldName) { 203 | Field field = null; 204 | Class fieldClass = null; 205 | Class caller = null; 206 | int modifiers = 0; 207 | try { 208 | field = tclass.getDeclaredField(fieldName); 209 | caller = sun.reflect.Reflection.getCallerClass(3); 210 | modifiers = field.getModifiers(); 211 | sun.reflect.misc.ReflectUtil.ensureMemberAccess( 212 | caller, tclass, null, modifiers); 213 | sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 214 | fieldClass = field.getType(); 215 | } catch (Exception ex) { 216 | throw new RuntimeException(ex); 217 | } 218 | 219 | if (vclass != fieldClass) 220 | throw new ClassCastException(); 221 | 222 | if (!Modifier.isVolatile(modifiers)) 223 | throw new IllegalArgumentException("Must be volatile type"); 224 | 225 | this.cclass = (Modifier.isProtected(modifiers) && 226 | caller != tclass) ? caller : null; 227 | this.tclass = tclass; 228 | if (vclass == Object.class) 229 | this.vclass = null; 230 | else 231 | this.vclass = vclass; 232 | offset = unsafe.objectFieldOffset(field); 233 | } 234 | 235 | void targetCheck(T obj) { 236 | if (!tclass.isInstance(obj)) 237 | throw new ClassCastException(); 238 | if (cclass != null) 239 | ensureProtectedAccess(obj); 240 | } 241 | 242 | void updateCheck(T obj, V update) { 243 | if (!tclass.isInstance(obj) || 244 | (update != null && vclass != null && !vclass.isInstance(update))) 245 | throw new ClassCastException(); 246 | if (cclass != null) 247 | ensureProtectedAccess(obj); 248 | } 249 | 250 | public boolean compareAndSet(T obj, V expect, V update) { 251 | if (obj == null || obj.getClass() != tclass || cclass != null || 252 | (update != null && vclass != null && 253 | vclass != update.getClass())) 254 | updateCheck(obj, update); 255 | return unsafe.compareAndSwapObject(obj, offset, expect, update); 256 | } 257 | 258 | public boolean weakCompareAndSet(T obj, V expect, V update) { 259 | // same implementation as strong form for now 260 | if (obj == null || obj.getClass() != tclass || cclass != null || 261 | (update != null && vclass != null && 262 | vclass != update.getClass())) 263 | updateCheck(obj, update); 264 | return unsafe.compareAndSwapObject(obj, offset, expect, update); 265 | } 266 | 267 | public void set(T obj, V newValue) { 268 | if (obj == null || obj.getClass() != tclass || cclass != null || 269 | (newValue != null && vclass != null && 270 | vclass != newValue.getClass())) 271 | updateCheck(obj, newValue); 272 | unsafe.putObjectVolatile(obj, offset, newValue); 273 | } 274 | 275 | public void lazySet(T obj, V newValue) { 276 | if (obj == null || obj.getClass() != tclass || cclass != null || 277 | (newValue != null && vclass != null && 278 | vclass != newValue.getClass())) 279 | updateCheck(obj, newValue); 280 | unsafe.putOrderedObject(obj, offset, newValue); 281 | } 282 | 283 | public V get(T obj) { 284 | if (obj == null || obj.getClass() != tclass || cclass != null) 285 | targetCheck(obj); 286 | return (V)unsafe.getObjectVolatile(obj, offset); 287 | } 288 | 289 | private void ensureProtectedAccess(T obj) { 290 | if (cclass.isInstance(obj)) { 291 | return; 292 | } 293 | throw new RuntimeException( 294 | new IllegalAccessException("Class " + 295 | cclass.getName() + 296 | " can not access a protected member of class " + 297 | tclass.getName() + 298 | " using an instance of " + 299 | obj.getClass().getName() 300 | ) 301 | ); 302 | } 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicIntegerFieldUpdater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | import java.lang.reflect.*; 39 | 40 | /** 41 | * A reflection-based utility that enables atomic updates to 42 | * designated {@code volatile int} fields of designated classes. 43 | * This class is designed for use in atomic data structures in which 44 | * several fields of the same node are independently subject to atomic 45 | * updates. 46 | * 47 | *

Note that the guarantees of the {@code compareAndSet} 48 | * method in this class are weaker than in other atomic classes. 49 | * Because this class cannot ensure that all uses of the field 50 | * are appropriate for purposes of atomic access, it can 51 | * guarantee atomicity only with respect to other invocations of 52 | * {@code compareAndSet} and {@code set} on the same updater. 53 | * 54 | * @since 1.5 55 | * @author Doug Lea 56 | * @param The type of the object holding the updatable field 57 | */ 58 | public abstract class AtomicIntegerFieldUpdater { 59 | /** 60 | * Creates and returns an updater for objects with the given field. 61 | * The Class argument is needed to check that reflective types and 62 | * generic types match. 63 | * 64 | * @param tclass the class of the objects holding the field 65 | * @param fieldName the name of the field to be updated 66 | * @return the updater 67 | * @throws IllegalArgumentException if the field is not a 68 | * volatile integer type 69 | * @throws RuntimeException with a nested reflection-based 70 | * exception if the class does not hold field or is the wrong type 71 | */ 72 | public static AtomicIntegerFieldUpdater newUpdater(Class tclass, String fieldName) { 73 | return new AtomicIntegerFieldUpdaterImpl(tclass, fieldName); 74 | } 75 | 76 | /** 77 | * Protected do-nothing constructor for use by subclasses. 78 | */ 79 | protected AtomicIntegerFieldUpdater() { 80 | } 81 | 82 | /** 83 | * Atomically sets the field of the given object managed by this updater 84 | * to the given updated value if the current value {@code ==} the 85 | * expected value. This method is guaranteed to be atomic with respect to 86 | * other calls to {@code compareAndSet} and {@code set}, but not 87 | * necessarily with respect to other changes in the field. 88 | * 89 | * @param obj An object whose field to conditionally set 90 | * @param expect the expected value 91 | * @param update the new value 92 | * @return true if successful 93 | * @throws ClassCastException if {@code obj} is not an instance 94 | * of the class possessing the field established in the constructor 95 | */ 96 | public abstract boolean compareAndSet(T obj, int expect, int update); 97 | 98 | /** 99 | * Atomically sets the field of the given object managed by this updater 100 | * to the given updated value if the current value {@code ==} the 101 | * expected value. This method is guaranteed to be atomic with respect to 102 | * other calls to {@code compareAndSet} and {@code set}, but not 103 | * necessarily with respect to other changes in the field. 104 | * 105 | *

May fail spuriously 106 | * and does not provide ordering guarantees, so is only rarely an 107 | * appropriate alternative to {@code compareAndSet}. 108 | * 109 | * @param obj An object whose field to conditionally set 110 | * @param expect the expected value 111 | * @param update the new value 112 | * @return true if successful 113 | * @throws ClassCastException if {@code obj} is not an instance 114 | * of the class possessing the field established in the constructor 115 | */ 116 | public abstract boolean weakCompareAndSet(T obj, int expect, int update); 117 | 118 | /** 119 | * Sets the field of the given object managed by this updater to the 120 | * given updated value. This operation is guaranteed to act as a volatile 121 | * store with respect to subsequent invocations of {@code compareAndSet}. 122 | * 123 | * @param obj An object whose field to set 124 | * @param newValue the new value 125 | */ 126 | public abstract void set(T obj, int newValue); 127 | 128 | /** 129 | * Eventually sets the field of the given object managed by this 130 | * updater to the given updated value. 131 | * 132 | * @param obj An object whose field to set 133 | * @param newValue the new value 134 | * @since 1.6 135 | */ 136 | public abstract void lazySet(T obj, int newValue); 137 | 138 | 139 | /** 140 | * Gets the current value held in the field of the given object managed 141 | * by this updater. 142 | * 143 | * @param obj An object whose field to get 144 | * @return the current value 145 | */ 146 | public abstract int get(T obj); 147 | 148 | /** 149 | * Atomically sets the field of the given object managed by this updater 150 | * to the given value and returns the old value. 151 | * 152 | * @param obj An object whose field to get and set 153 | * @param newValue the new value 154 | * @return the previous value 155 | */ 156 | public int getAndSet(T obj, int newValue) { 157 | for (;;) { 158 | int current = get(obj); 159 | if (compareAndSet(obj, current, newValue)) 160 | return current; 161 | } 162 | } 163 | 164 | /** 165 | * Atomically increments by one the current value of the field of the 166 | * given object managed by this updater. 167 | * 168 | * @param obj An object whose field to get and set 169 | * @return the previous value 170 | */ 171 | public int getAndIncrement(T obj) { 172 | for (;;) { 173 | int current = get(obj); 174 | int next = current + 1; 175 | if (compareAndSet(obj, current, next)) 176 | return current; 177 | } 178 | } 179 | 180 | /** 181 | * Atomically decrements by one the current value of the field of the 182 | * given object managed by this updater. 183 | * 184 | * @param obj An object whose field to get and set 185 | * @return the previous value 186 | */ 187 | public int getAndDecrement(T obj) { 188 | for (;;) { 189 | int current = get(obj); 190 | int next = current - 1; 191 | if (compareAndSet(obj, current, next)) 192 | return current; 193 | } 194 | } 195 | 196 | /** 197 | * Atomically adds the given value to the current value of the field of 198 | * the given object managed by this updater. 199 | * 200 | * @param obj An object whose field to get and set 201 | * @param delta the value to add 202 | * @return the previous value 203 | */ 204 | public int getAndAdd(T obj, int delta) { 205 | for (;;) { 206 | int current = get(obj); 207 | int next = current + delta; 208 | if (compareAndSet(obj, current, next)) 209 | return current; 210 | } 211 | } 212 | 213 | /** 214 | * Atomically increments by one the current value of the field of the 215 | * given object managed by this updater. 216 | * 217 | * @param obj An object whose field to get and set 218 | * @return the updated value 219 | */ 220 | public int incrementAndGet(T obj) { 221 | for (;;) { 222 | int current = get(obj); 223 | int next = current + 1; 224 | if (compareAndSet(obj, current, next)) 225 | return next; 226 | } 227 | } 228 | 229 | /** 230 | * Atomically decrements by one the current value of the field of the 231 | * given object managed by this updater. 232 | * 233 | * @param obj An object whose field to get and set 234 | * @return the updated value 235 | */ 236 | public int decrementAndGet(T obj) { 237 | for (;;) { 238 | int current = get(obj); 239 | int next = current - 1; 240 | if (compareAndSet(obj, current, next)) 241 | return next; 242 | } 243 | } 244 | 245 | /** 246 | * Atomically adds the given value to the current value of the field of 247 | * the given object managed by this updater. 248 | * 249 | * @param obj An object whose field to get and set 250 | * @param delta the value to add 251 | * @return the updated value 252 | */ 253 | public int addAndGet(T obj, int delta) { 254 | for (;;) { 255 | int current = get(obj); 256 | int next = current + delta; 257 | if (compareAndSet(obj, current, next)) 258 | return next; 259 | } 260 | } 261 | 262 | /** 263 | * Standard hotspot implementation using intrinsics 264 | */ 265 | private static class AtomicIntegerFieldUpdaterImpl extends AtomicIntegerFieldUpdater { 266 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 267 | private final long offset; 268 | private final Class tclass; 269 | private final Class cclass; 270 | 271 | AtomicIntegerFieldUpdaterImpl(Class tclass, String fieldName) { 272 | Field field = null; 273 | Class caller = null; 274 | int modifiers = 0; 275 | try { 276 | field = tclass.getDeclaredField(fieldName); 277 | caller = sun.reflect.Reflection.getCallerClass(3); 278 | modifiers = field.getModifiers(); 279 | sun.reflect.misc.ReflectUtil.ensureMemberAccess( 280 | caller, tclass, null, modifiers); 281 | sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 282 | } catch (Exception ex) { 283 | throw new RuntimeException(ex); 284 | } 285 | 286 | Class fieldt = field.getType(); 287 | if (fieldt != int.class) 288 | throw new IllegalArgumentException("Must be integer type"); 289 | 290 | if (!Modifier.isVolatile(modifiers)) 291 | throw new IllegalArgumentException("Must be volatile type"); 292 | 293 | this.cclass = (Modifier.isProtected(modifiers) && 294 | caller != tclass) ? caller : null; 295 | this.tclass = tclass; 296 | offset = unsafe.objectFieldOffset(field); 297 | } 298 | 299 | private void fullCheck(T obj) { 300 | if (!tclass.isInstance(obj)) 301 | throw new ClassCastException(); 302 | if (cclass != null) 303 | ensureProtectedAccess(obj); 304 | } 305 | 306 | public boolean compareAndSet(T obj, int expect, int update) { 307 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 308 | return unsafe.compareAndSwapInt(obj, offset, expect, update); 309 | } 310 | 311 | public boolean weakCompareAndSet(T obj, int expect, int update) { 312 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 313 | return unsafe.compareAndSwapInt(obj, offset, expect, update); 314 | } 315 | 316 | public void set(T obj, int newValue) { 317 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 318 | unsafe.putIntVolatile(obj, offset, newValue); 319 | } 320 | 321 | public void lazySet(T obj, int newValue) { 322 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 323 | unsafe.putOrderedInt(obj, offset, newValue); 324 | } 325 | 326 | public final int get(T obj) { 327 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 328 | return unsafe.getIntVolatile(obj, offset); 329 | } 330 | 331 | private void ensureProtectedAccess(T obj) { 332 | if (cclass.isInstance(obj)) { 333 | return; 334 | } 335 | throw new RuntimeException( 336 | new IllegalAccessException("Class " + 337 | cclass.getName() + 338 | " can not access a protected member of class " + 339 | tclass.getName() + 340 | " using an instance of " + 341 | obj.getClass().getName() 342 | ) 343 | ); 344 | } 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/locks/LockSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.locks; 37 | import java.util.concurrent.*; 38 | import sun.misc.Unsafe; 39 | 40 | 41 | /** 42 | * Basic thread blocking primitives for creating locks and other 43 | * synchronization classes. 44 | * 45 | *

This class associates, with each thread that uses it, a permit 46 | * (in the sense of the {@link java.util.concurrent.Semaphore 47 | * Semaphore} class). A call to {@code park} will return immediately 48 | * if the permit is available, consuming it in the process; otherwise 49 | * it may block. A call to {@code unpark} makes the permit 50 | * available, if it was not already available. (Unlike with Semaphores 51 | * though, permits do not accumulate. There is at most one.) 52 | * 53 | *

Methods {@code park} and {@code unpark} provide efficient 54 | * means of blocking and unblocking threads that do not encounter the 55 | * problems that cause the deprecated methods {@code Thread.suspend} 56 | * and {@code Thread.resume} to be unusable for such purposes: Races 57 | * between one thread invoking {@code park} and another thread trying 58 | * to {@code unpark} it will preserve liveness, due to the 59 | * permit. Additionally, {@code park} will return if the caller's 60 | * thread was interrupted, and timeout versions are supported. The 61 | * {@code park} method may also return at any other time, for "no 62 | * reason", so in general must be invoked within a loop that rechecks 63 | * conditions upon return. In this sense {@code park} serves as an 64 | * optimization of a "busy wait" that does not waste as much time 65 | * spinning, but must be paired with an {@code unpark} to be 66 | * effective. 67 | * 68 | *

The three forms of {@code park} each also support a 69 | * {@code blocker} object parameter. This object is recorded while 70 | * the thread is blocked to permit monitoring and diagnostic tools to 71 | * identify the reasons that threads are blocked. (Such tools may 72 | * access blockers using method {@link #getBlocker}.) The use of these 73 | * forms rather than the original forms without this parameter is 74 | * strongly encouraged. The normal argument to supply as a 75 | * {@code blocker} within a lock implementation is {@code this}. 76 | * 77 | *

These methods are designed to be used as tools for creating 78 | * higher-level synchronization utilities, and are not in themselves 79 | * useful for most concurrency control applications. The {@code park} 80 | * method is designed for use only in constructions of the form: 81 | *

while (!canProceed()) { ... LockSupport.park(this); }
82 | * where neither {@code canProceed} nor any other actions prior to the 83 | * call to {@code park} entail locking or blocking. Because only one 84 | * permit is associated with each thread, any intermediary uses of 85 | * {@code park} could interfere with its intended effects. 86 | * 87 | *

Sample Usage. Here is a sketch of a first-in-first-out 88 | * non-reentrant lock class: 89 | *

{@code
 90 |  * class FIFOMutex {
 91 |  *   private final AtomicBoolean locked = new AtomicBoolean(false);
 92 |  *   private final Queue waiters
 93 |  *     = new ConcurrentLinkedQueue();
 94 |  *
 95 |  *   public void lock() {
 96 |  *     boolean wasInterrupted = false;
 97 |  *     Thread current = Thread.currentThread();
 98 |  *     waiters.add(current);
 99 |  *
100 |  *     // Block while not first in queue or cannot acquire lock
101 |  *     while (waiters.peek() != current ||
102 |  *            !locked.compareAndSet(false, true)) {
103 |  *        LockSupport.park(this);
104 |  *        if (Thread.interrupted()) // ignore interrupts while waiting
105 |  *          wasInterrupted = true;
106 |  *     }
107 |  *
108 |  *     waiters.remove();
109 |  *     if (wasInterrupted)          // reassert interrupt status on exit
110 |  *        current.interrupt();
111 |  *   }
112 |  *
113 |  *   public void unlock() {
114 |  *     locked.set(false);
115 |  *     LockSupport.unpark(waiters.peek());
116 |  *   }
117 |  * }}
118 | */ 119 | 120 | public class LockSupport { 121 | private LockSupport() {} // Cannot be instantiated. 122 | 123 | // Hotspot implementation via intrinsics API 124 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 125 | private static final long parkBlockerOffset; 126 | 127 | static { 128 | try { 129 | parkBlockerOffset = unsafe.objectFieldOffset 130 | (java.lang.Thread.class.getDeclaredField("parkBlocker")); 131 | } catch (Exception ex) { throw new Error(ex); } 132 | } 133 | 134 | private static void setBlocker(Thread t, Object arg) { 135 | // Even though volatile, hotspot doesn't need a write barrier here. 136 | unsafe.putObject(t, parkBlockerOffset, arg); 137 | } 138 | 139 | /** 140 | * Makes available the permit for the given thread, if it 141 | * was not already available. If the thread was blocked on 142 | * {@code park} then it will unblock. Otherwise, its next call 143 | * to {@code park} is guaranteed not to block. This operation 144 | * is not guaranteed to have any effect at all if the given 145 | * thread has not been started. 146 | * 147 | * @param thread the thread to unpark, or {@code null}, in which case 148 | * this operation has no effect 149 | */ 150 | public static void unpark(Thread thread) { 151 | if (thread != null) 152 | unsafe.unpark(thread); 153 | } 154 | 155 | /** 156 | * Disables the current thread for thread scheduling purposes unless the 157 | * permit is available. 158 | * 159 | *

If the permit is available then it is consumed and the call returns 160 | * immediately; otherwise 161 | * the current thread becomes disabled for thread scheduling 162 | * purposes and lies dormant until one of three things happens: 163 | * 164 | *

    165 | *
  • Some other thread invokes {@link #unpark unpark} with the 166 | * current thread as the target; or 167 | * 168 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} 169 | * the current thread; or 170 | * 171 | *
  • The call spuriously (that is, for no reason) returns. 172 | *
173 | * 174 | *

This method does not report which of these caused the 175 | * method to return. Callers should re-check the conditions which caused 176 | * the thread to park in the first place. Callers may also determine, 177 | * for example, the interrupt status of the thread upon return. 178 | * 179 | * @param blocker the synchronization object responsible for this 180 | * thread parking 181 | * @since 1.6 182 | */ 183 | public static void park(Object blocker) { 184 | Thread t = Thread.currentThread(); 185 | setBlocker(t, blocker); 186 | unsafe.park(false, 0L); 187 | setBlocker(t, null); 188 | } 189 | 190 | /** 191 | * Disables the current thread for thread scheduling purposes, for up to 192 | * the specified waiting time, unless the permit is available. 193 | * 194 | *

If the permit is available then it is consumed and the call 195 | * returns immediately; otherwise the current thread becomes disabled 196 | * for thread scheduling purposes and lies dormant until one of four 197 | * things happens: 198 | * 199 | *

    200 | *
  • Some other thread invokes {@link #unpark unpark} with the 201 | * current thread as the target; or 202 | * 203 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} 204 | * the current thread; or 205 | * 206 | *
  • The specified waiting time elapses; or 207 | * 208 | *
  • The call spuriously (that is, for no reason) returns. 209 | *
210 | * 211 | *

This method does not report which of these caused the 212 | * method to return. Callers should re-check the conditions which caused 213 | * the thread to park in the first place. Callers may also determine, 214 | * for example, the interrupt status of the thread, or the elapsed time 215 | * upon return. 216 | * 217 | * @param blocker the synchronization object responsible for this 218 | * thread parking 219 | * @param nanos the maximum number of nanoseconds to wait 220 | * @since 1.6 221 | */ 222 | public static void parkNanos(Object blocker, long nanos) { 223 | if (nanos > 0) { 224 | Thread t = Thread.currentThread(); 225 | setBlocker(t, blocker); 226 | unsafe.park(false, nanos); 227 | setBlocker(t, null); 228 | } 229 | } 230 | 231 | /** 232 | * Disables the current thread for thread scheduling purposes, until 233 | * the specified deadline, unless the permit is available. 234 | * 235 | *

If the permit is available then it is consumed and the call 236 | * returns immediately; otherwise the current thread becomes disabled 237 | * for thread scheduling purposes and lies dormant until one of four 238 | * things happens: 239 | * 240 | *

    241 | *
  • Some other thread invokes {@link #unpark unpark} with the 242 | * current thread as the target; or 243 | * 244 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} the 245 | * current thread; or 246 | * 247 | *
  • The specified deadline passes; or 248 | * 249 | *
  • The call spuriously (that is, for no reason) returns. 250 | *
251 | * 252 | *

This method does not report which of these caused the 253 | * method to return. Callers should re-check the conditions which caused 254 | * the thread to park in the first place. Callers may also determine, 255 | * for example, the interrupt status of the thread, or the current time 256 | * upon return. 257 | * 258 | * @param blocker the synchronization object responsible for this 259 | * thread parking 260 | * @param deadline the absolute time, in milliseconds from the Epoch, 261 | * to wait until 262 | * @since 1.6 263 | */ 264 | public static void parkUntil(Object blocker, long deadline) { 265 | Thread t = Thread.currentThread(); 266 | setBlocker(t, blocker); 267 | unsafe.park(true, deadline); 268 | setBlocker(t, null); 269 | } 270 | 271 | /** 272 | * Returns the blocker object supplied to the most recent 273 | * invocation of a park method that has not yet unblocked, or null 274 | * if not blocked. The value returned is just a momentary 275 | * snapshot -- the thread may have since unblocked or blocked on a 276 | * different blocker object. 277 | * 278 | * @param t the thread 279 | * @return the blocker 280 | * @throws NullPointerException if argument is null 281 | * @since 1.6 282 | */ 283 | public static Object getBlocker(Thread t) { 284 | if (t == null) 285 | throw new NullPointerException(); 286 | return unsafe.getObjectVolatile(t, parkBlockerOffset); 287 | } 288 | 289 | /** 290 | * Disables the current thread for thread scheduling purposes unless the 291 | * permit is available. 292 | * 293 | *

If the permit is available then it is consumed and the call 294 | * returns immediately; otherwise the current thread becomes disabled 295 | * for thread scheduling purposes and lies dormant until one of three 296 | * things happens: 297 | * 298 | *

    299 | * 300 | *
  • Some other thread invokes {@link #unpark unpark} with the 301 | * current thread as the target; or 302 | * 303 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} 304 | * the current thread; or 305 | * 306 | *
  • The call spuriously (that is, for no reason) returns. 307 | *
308 | * 309 | *

This method does not report which of these caused the 310 | * method to return. Callers should re-check the conditions which caused 311 | * the thread to park in the first place. Callers may also determine, 312 | * for example, the interrupt status of the thread upon return. 313 | */ 314 | public static void park() { 315 | unsafe.park(false, 0L); 316 | } 317 | 318 | /** 319 | * Disables the current thread for thread scheduling purposes, for up to 320 | * the specified waiting time, unless the permit is available. 321 | * 322 | *

If the permit is available then it is consumed and the call 323 | * returns immediately; otherwise the current thread becomes disabled 324 | * for thread scheduling purposes and lies dormant until one of four 325 | * things happens: 326 | * 327 | *

    328 | *
  • Some other thread invokes {@link #unpark unpark} with the 329 | * current thread as the target; or 330 | * 331 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} 332 | * the current thread; or 333 | * 334 | *
  • The specified waiting time elapses; or 335 | * 336 | *
  • The call spuriously (that is, for no reason) returns. 337 | *
338 | * 339 | *

This method does not report which of these caused the 340 | * method to return. Callers should re-check the conditions which caused 341 | * the thread to park in the first place. Callers may also determine, 342 | * for example, the interrupt status of the thread, or the elapsed time 343 | * upon return. 344 | * 345 | * @param nanos the maximum number of nanoseconds to wait 346 | */ 347 | public static void parkNanos(long nanos) { 348 | if (nanos > 0) 349 | unsafe.park(false, nanos); 350 | } 351 | 352 | /** 353 | * Disables the current thread for thread scheduling purposes, until 354 | * the specified deadline, unless the permit is available. 355 | * 356 | *

If the permit is available then it is consumed and the call 357 | * returns immediately; otherwise the current thread becomes disabled 358 | * for thread scheduling purposes and lies dormant until one of four 359 | * things happens: 360 | * 361 | *

    362 | *
  • Some other thread invokes {@link #unpark unpark} with the 363 | * current thread as the target; or 364 | * 365 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} 366 | * the current thread; or 367 | * 368 | *
  • The specified deadline passes; or 369 | * 370 | *
  • The call spuriously (that is, for no reason) returns. 371 | *
372 | * 373 | *

This method does not report which of these caused the 374 | * method to return. Callers should re-check the conditions which caused 375 | * the thread to park in the first place. Callers may also determine, 376 | * for example, the interrupt status of the thread, or the current time 377 | * upon return. 378 | * 379 | * @param deadline the absolute time, in milliseconds from the Epoch, 380 | * to wait until 381 | */ 382 | public static void parkUntil(long deadline) { 383 | unsafe.park(true, deadline); 384 | } 385 | } 386 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/locks/Lock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.locks; 37 | import java.util.concurrent.TimeUnit; 38 | 39 | /** 40 | * {@code Lock} implementations provide more extensive locking 41 | * operations than can be obtained using {@code synchronized} methods 42 | * and statements. They allow more flexible structuring, may have 43 | * quite different properties, and may support multiple associated 44 | * {@link Condition} objects. 45 | * 46 | *

A lock is a tool for controlling access to a shared resource by 47 | * multiple threads. Commonly, a lock provides exclusive access to a 48 | * shared resource: only one thread at a time can acquire the lock and 49 | * all access to the shared resource requires that the lock be 50 | * acquired first. However, some locks may allow concurrent access to 51 | * a shared resource, such as the read lock of a {@link ReadWriteLock}. 52 | * 53 | *

The use of {@code synchronized} methods or statements provides 54 | * access to the implicit monitor lock associated with every object, but 55 | * forces all lock acquisition and release to occur in a block-structured way: 56 | * when multiple locks are acquired they must be released in the opposite 57 | * order, and all locks must be released in the same lexical scope in which 58 | * they were acquired. 59 | * 60 | *

While the scoping mechanism for {@code synchronized} methods 61 | * and statements makes it much easier to program with monitor locks, 62 | * and helps avoid many common programming errors involving locks, 63 | * there are occasions where you need to work with locks in a more 64 | * flexible way. For example, some algorithms for traversing 65 | * concurrently accessed data structures require the use of 66 | * "hand-over-hand" or "chain locking": you 67 | * acquire the lock of node A, then node B, then release A and acquire 68 | * C, then release B and acquire D and so on. Implementations of the 69 | * {@code Lock} interface enable the use of such techniques by 70 | * allowing a lock to be acquired and released in different scopes, 71 | * and allowing multiple locks to be acquired and released in any 72 | * order. 73 | * 74 | *

With this increased flexibility comes additional 75 | * responsibility. The absence of block-structured locking removes the 76 | * automatic release of locks that occurs with {@code synchronized} 77 | * methods and statements. In most cases, the following idiom 78 | * should be used: 79 | * 80 | *

     Lock l = ...;
 81 |  *     l.lock();
 82 |  *     try {
 83 |  *         // access the resource protected by this lock
 84 |  *     } finally {
 85 |  *         l.unlock();
 86 |  *     }
 87 |  * 
88 | * 89 | * When locking and unlocking occur in different scopes, care must be 90 | * taken to ensure that all code that is executed while the lock is 91 | * held is protected by try-finally or try-catch to ensure that the 92 | * lock is released when necessary. 93 | * 94 | *

{@code Lock} implementations provide additional functionality 95 | * over the use of {@code synchronized} methods and statements by 96 | * providing a non-blocking attempt to acquire a lock ({@link 97 | * #tryLock()}), an attempt to acquire the lock that can be 98 | * interrupted ({@link #lockInterruptibly}, and an attempt to acquire 99 | * the lock that can timeout ({@link #tryLock(long, TimeUnit)}). 100 | * 101 | *

A {@code Lock} class can also provide behavior and semantics 102 | * that is quite different from that of the implicit monitor lock, 103 | * such as guaranteed ordering, non-reentrant usage, or deadlock 104 | * detection. If an implementation provides such specialized semantics 105 | * then the implementation must document those semantics. 106 | * 107 | *

Note that {@code Lock} instances are just normal objects and can 108 | * themselves be used as the target in a {@code synchronized} statement. 109 | * Acquiring the 110 | * monitor lock of a {@code Lock} instance has no specified relationship 111 | * with invoking any of the {@link #lock} methods of that instance. 112 | * It is recommended that to avoid confusion you never use {@code Lock} 113 | * instances in this way, except within their own implementation. 114 | * 115 | *

Except where noted, passing a {@code null} value for any 116 | * parameter will result in a {@link NullPointerException} being 117 | * thrown. 118 | * 119 | *

Memory Synchronization

120 | * 121 | *

All {@code Lock} implementations must enforce the same 122 | * memory synchronization semantics as provided by the built-in monitor 123 | * lock, as described in section 17.4 of 124 | * The Java™ Language Specification: 125 | *

    126 | *
  • A successful {@code lock} operation has the same memory 127 | * synchronization effects as a successful Lock action. 128 | *
  • A successful {@code unlock} operation has the same 129 | * memory synchronization effects as a successful Unlock action. 130 | *
131 | * 132 | * Unsuccessful locking and unlocking operations, and reentrant 133 | * locking/unlocking operations, do not require any memory 134 | * synchronization effects. 135 | * 136 | *

Implementation Considerations

137 | * 138 | *

The three forms of lock acquisition (interruptible, 139 | * non-interruptible, and timed) may differ in their performance 140 | * characteristics, ordering guarantees, or other implementation 141 | * qualities. Further, the ability to interrupt the ongoing 142 | * acquisition of a lock may not be available in a given {@code Lock} 143 | * class. Consequently, an implementation is not required to define 144 | * exactly the same guarantees or semantics for all three forms of 145 | * lock acquisition, nor is it required to support interruption of an 146 | * ongoing lock acquisition. An implementation is required to clearly 147 | * document the semantics and guarantees provided by each of the 148 | * locking methods. It must also obey the interruption semantics as 149 | * defined in this interface, to the extent that interruption of lock 150 | * acquisition is supported: which is either totally, or only on 151 | * method entry. 152 | * 153 | *

As interruption generally implies cancellation, and checks for 154 | * interruption are often infrequent, an implementation can favor responding 155 | * to an interrupt over normal method return. This is true even if it can be 156 | * shown that the interrupt occurred after another action may have unblocked 157 | * the thread. An implementation should document this behavior. 158 | * 159 | * @see ReentrantLock 160 | * @see Condition 161 | * @see ReadWriteLock 162 | * 163 | * @since 1.5 164 | * @author Doug Lea 165 | */ 166 | public interface Lock { 167 | 168 | /** 169 | * Acquires the lock. 170 | * 171 | *

If the lock is not available then the current thread becomes 172 | * disabled for thread scheduling purposes and lies dormant until the 173 | * lock has been acquired. 174 | * 175 | *

Implementation Considerations 176 | * 177 | *

A {@code Lock} implementation may be able to detect erroneous use 178 | * of the lock, such as an invocation that would cause deadlock, and 179 | * may throw an (unchecked) exception in such circumstances. The 180 | * circumstances and the exception type must be documented by that 181 | * {@code Lock} implementation. 182 | */ 183 | void lock(); 184 | 185 | /** 186 | * Acquires the lock unless the current thread is 187 | * {@linkplain Thread#interrupt interrupted}. 188 | * 189 | *

Acquires the lock if it is available and returns immediately. 190 | * 191 | *

If the lock is not available then the current thread becomes 192 | * disabled for thread scheduling purposes and lies dormant until 193 | * one of two things happens: 194 | * 195 | *

    196 | *
  • The lock is acquired by the current thread; or 197 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} the 198 | * current thread, and interruption of lock acquisition is supported. 199 | *
200 | * 201 | *

If the current thread: 202 | *

    203 | *
  • has its interrupted status set on entry to this method; or 204 | *
  • is {@linkplain Thread#interrupt interrupted} while acquiring the 205 | * lock, and interruption of lock acquisition is supported, 206 | *
207 | * then {@link InterruptedException} is thrown and the current thread's 208 | * interrupted status is cleared. 209 | * 210 | *

Implementation Considerations 211 | * 212 | *

The ability to interrupt a lock acquisition in some 213 | * implementations may not be possible, and if possible may be an 214 | * expensive operation. The programmer should be aware that this 215 | * may be the case. An implementation should document when this is 216 | * the case. 217 | * 218 | *

An implementation can favor responding to an interrupt over 219 | * normal method return. 220 | * 221 | *

A {@code Lock} implementation may be able to detect 222 | * erroneous use of the lock, such as an invocation that would 223 | * cause deadlock, and may throw an (unchecked) exception in such 224 | * circumstances. The circumstances and the exception type must 225 | * be documented by that {@code Lock} implementation. 226 | * 227 | * @throws InterruptedException if the current thread is 228 | * interrupted while acquiring the lock (and interruption 229 | * of lock acquisition is supported). 230 | */ 231 | void lockInterruptibly() throws InterruptedException; 232 | 233 | /** 234 | * Acquires the lock only if it is free at the time of invocation. 235 | * 236 | *

Acquires the lock if it is available and returns immediately 237 | * with the value {@code true}. 238 | * If the lock is not available then this method will return 239 | * immediately with the value {@code false}. 240 | * 241 | *

A typical usage idiom for this method would be: 242 | *

243 |      *      Lock lock = ...;
244 |      *      if (lock.tryLock()) {
245 |      *          try {
246 |      *              // manipulate protected state
247 |      *          } finally {
248 |      *              lock.unlock();
249 |      *          }
250 |      *      } else {
251 |      *          // perform alternative actions
252 |      *      }
253 |      * 
254 | * This usage ensures that the lock is unlocked if it was acquired, and 255 | * doesn't try to unlock if the lock was not acquired. 256 | * 257 | * @return {@code true} if the lock was acquired and 258 | * {@code false} otherwise 259 | */ 260 | boolean tryLock(); 261 | 262 | /** 263 | * Acquires the lock if it is free within the given waiting time and the 264 | * current thread has not been {@linkplain Thread#interrupt interrupted}. 265 | * 266 | *

If the lock is available this method returns immediately 267 | * with the value {@code true}. 268 | * If the lock is not available then 269 | * the current thread becomes disabled for thread scheduling 270 | * purposes and lies dormant until one of three things happens: 271 | *

    272 | *
  • The lock is acquired by the current thread; or 273 | *
  • Some other thread {@linkplain Thread#interrupt interrupts} the 274 | * current thread, and interruption of lock acquisition is supported; or 275 | *
  • The specified waiting time elapses 276 | *
277 | * 278 | *

If the lock is acquired then the value {@code true} is returned. 279 | * 280 | *

If the current thread: 281 | *

    282 | *
  • has its interrupted status set on entry to this method; or 283 | *
  • is {@linkplain Thread#interrupt interrupted} while acquiring 284 | * the lock, and interruption of lock acquisition is supported, 285 | *
286 | * then {@link InterruptedException} is thrown and the current thread's 287 | * interrupted status is cleared. 288 | * 289 | *

If the specified waiting time elapses then the value {@code false} 290 | * is returned. 291 | * If the time is 292 | * less than or equal to zero, the method will not wait at all. 293 | * 294 | *

Implementation Considerations 295 | * 296 | *

The ability to interrupt a lock acquisition in some implementations 297 | * may not be possible, and if possible may 298 | * be an expensive operation. 299 | * The programmer should be aware that this may be the case. An 300 | * implementation should document when this is the case. 301 | * 302 | *

An implementation can favor responding to an interrupt over normal 303 | * method return, or reporting a timeout. 304 | * 305 | *

A {@code Lock} implementation may be able to detect 306 | * erroneous use of the lock, such as an invocation that would cause 307 | * deadlock, and may throw an (unchecked) exception in such circumstances. 308 | * The circumstances and the exception type must be documented by that 309 | * {@code Lock} implementation. 310 | * 311 | * @param time the maximum time to wait for the lock 312 | * @param unit the time unit of the {@code time} argument 313 | * @return {@code true} if the lock was acquired and {@code false} 314 | * if the waiting time elapsed before the lock was acquired 315 | * 316 | * @throws InterruptedException if the current thread is interrupted 317 | * while acquiring the lock (and interruption of lock 318 | * acquisition is supported) 319 | */ 320 | boolean tryLock(long time, TimeUnit unit) throws InterruptedException; 321 | 322 | /** 323 | * Releases the lock. 324 | * 325 | *

Implementation Considerations 326 | * 327 | *

A {@code Lock} implementation will usually impose 328 | * restrictions on which thread can release a lock (typically only the 329 | * holder of the lock can release it) and may throw 330 | * an (unchecked) exception if the restriction is violated. 331 | * Any restrictions and the exception 332 | * type must be documented by that {@code Lock} implementation. 333 | */ 334 | void unlock(); 335 | 336 | /** 337 | * Returns a new {@link Condition} instance that is bound to this 338 | * {@code Lock} instance. 339 | * 340 | *

Before waiting on the condition the lock must be held by the 341 | * current thread. 342 | * A call to {@link Condition#await()} will atomically release the lock 343 | * before waiting and re-acquire the lock before the wait returns. 344 | * 345 | *

Implementation Considerations 346 | * 347 | *

The exact operation of the {@link Condition} instance depends on 348 | * the {@code Lock} implementation and must be documented by that 349 | * implementation. 350 | * 351 | * @return A new {@link Condition} instance for this {@code Lock} instance 352 | * @throws UnsupportedOperationException if this {@code Lock} 353 | * implementation does not support conditions 354 | */ 355 | Condition newCondition(); 356 | } 357 | -------------------------------------------------------------------------------- /TheArtOFMultiprocessorProgramming/concurrent/atomic/AtomicLongFieldUpdater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 | * 4 | * This code is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License version 2 only, as 6 | * published by the Free Software Foundation. Oracle designates this 7 | * particular file as subject to the "Classpath" exception as provided 8 | * by Oracle in the LICENSE file that accompanied this code. 9 | * 10 | * This code is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * version 2 for more details (a copy is included in the LICENSE file that 14 | * accompanied this code). 15 | * 16 | * You should have received a copy of the GNU General Public License version 17 | * 2 along with this work; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | * or visit www.oracle.com if you need additional information or have any 22 | * questions. 23 | */ 24 | 25 | /* 26 | * This file is available under and governed by the GNU General Public 27 | * License version 2 only, as published by the Free Software Foundation. 28 | * However, the following notice accompanied the original version of this 29 | * file: 30 | * 31 | * Written by Doug Lea with assistance from members of JCP JSR-166 32 | * Expert Group and released to the public domain, as explained at 33 | * http://creativecommons.org/publicdomain/zero/1.0/ 34 | */ 35 | 36 | package java.util.concurrent.atomic; 37 | import sun.misc.Unsafe; 38 | import java.lang.reflect.*; 39 | 40 | /** 41 | * A reflection-based utility that enables atomic updates to 42 | * designated {@code volatile long} fields of designated classes. 43 | * This class is designed for use in atomic data structures in which 44 | * several fields of the same node are independently subject to atomic 45 | * updates. 46 | * 47 | *

Note that the guarantees of the {@code compareAndSet} 48 | * method in this class are weaker than in other atomic classes. 49 | * Because this class cannot ensure that all uses of the field 50 | * are appropriate for purposes of atomic access, it can 51 | * guarantee atomicity only with respect to other invocations of 52 | * {@code compareAndSet} and {@code set} on the same updater. 53 | * 54 | * @since 1.5 55 | * @author Doug Lea 56 | * @param The type of the object holding the updatable field 57 | */ 58 | public abstract class AtomicLongFieldUpdater { 59 | /** 60 | * Creates and returns an updater for objects with the given field. 61 | * The Class argument is needed to check that reflective types and 62 | * generic types match. 63 | * 64 | * @param tclass the class of the objects holding the field 65 | * @param fieldName the name of the field to be updated. 66 | * @return the updater 67 | * @throws IllegalArgumentException if the field is not a 68 | * volatile long type. 69 | * @throws RuntimeException with a nested reflection-based 70 | * exception if the class does not hold field or is the wrong type. 71 | */ 72 | public static AtomicLongFieldUpdater newUpdater(Class tclass, String fieldName) { 73 | if (AtomicLong.VM_SUPPORTS_LONG_CAS) 74 | return new CASUpdater(tclass, fieldName); 75 | else 76 | return new LockedUpdater(tclass, fieldName); 77 | } 78 | 79 | /** 80 | * Protected do-nothing constructor for use by subclasses. 81 | */ 82 | protected AtomicLongFieldUpdater() { 83 | } 84 | 85 | /** 86 | * Atomically sets the field of the given object managed by this updater 87 | * to the given updated value if the current value {@code ==} the 88 | * expected value. This method is guaranteed to be atomic with respect to 89 | * other calls to {@code compareAndSet} and {@code set}, but not 90 | * necessarily with respect to other changes in the field. 91 | * 92 | * @param obj An object whose field to conditionally set 93 | * @param expect the expected value 94 | * @param update the new value 95 | * @return true if successful. 96 | * @throws ClassCastException if {@code obj} is not an instance 97 | * of the class possessing the field established in the constructor. 98 | */ 99 | public abstract boolean compareAndSet(T obj, long expect, long update); 100 | 101 | /** 102 | * Atomically sets the field of the given object managed by this updater 103 | * to the given updated value if the current value {@code ==} the 104 | * expected value. This method is guaranteed to be atomic with respect to 105 | * other calls to {@code compareAndSet} and {@code set}, but not 106 | * necessarily with respect to other changes in the field. 107 | * 108 | *

May fail spuriously 109 | * and does not provide ordering guarantees, so is only rarely an 110 | * appropriate alternative to {@code compareAndSet}. 111 | * 112 | * @param obj An object whose field to conditionally set 113 | * @param expect the expected value 114 | * @param update the new value 115 | * @return true if successful. 116 | * @throws ClassCastException if {@code obj} is not an instance 117 | * of the class possessing the field established in the constructor. 118 | */ 119 | public abstract boolean weakCompareAndSet(T obj, long expect, long update); 120 | 121 | /** 122 | * Sets the field of the given object managed by this updater to the 123 | * given updated value. This operation is guaranteed to act as a volatile 124 | * store with respect to subsequent invocations of {@code compareAndSet}. 125 | * 126 | * @param obj An object whose field to set 127 | * @param newValue the new value 128 | */ 129 | public abstract void set(T obj, long newValue); 130 | 131 | /** 132 | * Eventually sets the field of the given object managed by this 133 | * updater to the given updated value. 134 | * 135 | * @param obj An object whose field to set 136 | * @param newValue the new value 137 | * @since 1.6 138 | */ 139 | public abstract void lazySet(T obj, long newValue); 140 | 141 | /** 142 | * Gets the current value held in the field of the given object managed 143 | * by this updater. 144 | * 145 | * @param obj An object whose field to get 146 | * @return the current value 147 | */ 148 | public abstract long get(T obj); 149 | 150 | /** 151 | * Atomically sets the field of the given object managed by this updater 152 | * to the given value and returns the old value. 153 | * 154 | * @param obj An object whose field to get and set 155 | * @param newValue the new value 156 | * @return the previous value 157 | */ 158 | public long getAndSet(T obj, long newValue) { 159 | for (;;) { 160 | long current = get(obj); 161 | if (compareAndSet(obj, current, newValue)) 162 | return current; 163 | } 164 | } 165 | 166 | /** 167 | * Atomically increments by one the current value of the field of the 168 | * given object managed by this updater. 169 | * 170 | * @param obj An object whose field to get and set 171 | * @return the previous value 172 | */ 173 | public long getAndIncrement(T obj) { 174 | for (;;) { 175 | long current = get(obj); 176 | long next = current + 1; 177 | if (compareAndSet(obj, current, next)) 178 | return current; 179 | } 180 | } 181 | 182 | /** 183 | * Atomically decrements by one the current value of the field of the 184 | * given object managed by this updater. 185 | * 186 | * @param obj An object whose field to get and set 187 | * @return the previous value 188 | */ 189 | public long getAndDecrement(T obj) { 190 | for (;;) { 191 | long current = get(obj); 192 | long next = current - 1; 193 | if (compareAndSet(obj, current, next)) 194 | return current; 195 | } 196 | } 197 | 198 | /** 199 | * Atomically adds the given value to the current value of the field of 200 | * the given object managed by this updater. 201 | * 202 | * @param obj An object whose field to get and set 203 | * @param delta the value to add 204 | * @return the previous value 205 | */ 206 | public long getAndAdd(T obj, long delta) { 207 | for (;;) { 208 | long current = get(obj); 209 | long next = current + delta; 210 | if (compareAndSet(obj, current, next)) 211 | return current; 212 | } 213 | } 214 | 215 | /** 216 | * Atomically increments by one the current value of the field of the 217 | * given object managed by this updater. 218 | * 219 | * @param obj An object whose field to get and set 220 | * @return the updated value 221 | */ 222 | public long incrementAndGet(T obj) { 223 | for (;;) { 224 | long current = get(obj); 225 | long next = current + 1; 226 | if (compareAndSet(obj, current, next)) 227 | return next; 228 | } 229 | } 230 | 231 | /** 232 | * Atomically decrements by one the current value of the field of the 233 | * given object managed by this updater. 234 | * 235 | * @param obj An object whose field to get and set 236 | * @return the updated value 237 | */ 238 | public long decrementAndGet(T obj) { 239 | for (;;) { 240 | long current = get(obj); 241 | long next = current - 1; 242 | if (compareAndSet(obj, current, next)) 243 | return next; 244 | } 245 | } 246 | 247 | /** 248 | * Atomically adds the given value to the current value of the field of 249 | * the given object managed by this updater. 250 | * 251 | * @param obj An object whose field to get and set 252 | * @param delta the value to add 253 | * @return the updated value 254 | */ 255 | public long addAndGet(T obj, long delta) { 256 | for (;;) { 257 | long current = get(obj); 258 | long next = current + delta; 259 | if (compareAndSet(obj, current, next)) 260 | return next; 261 | } 262 | } 263 | 264 | private static class CASUpdater extends AtomicLongFieldUpdater { 265 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 266 | private final long offset; 267 | private final Class tclass; 268 | private final Class cclass; 269 | 270 | CASUpdater(Class tclass, String fieldName) { 271 | Field field = null; 272 | Class caller = null; 273 | int modifiers = 0; 274 | try { 275 | field = tclass.getDeclaredField(fieldName); 276 | caller = sun.reflect.Reflection.getCallerClass(3); 277 | modifiers = field.getModifiers(); 278 | sun.reflect.misc.ReflectUtil.ensureMemberAccess( 279 | caller, tclass, null, modifiers); 280 | sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 281 | } catch (Exception ex) { 282 | throw new RuntimeException(ex); 283 | } 284 | 285 | Class fieldt = field.getType(); 286 | if (fieldt != long.class) 287 | throw new IllegalArgumentException("Must be long type"); 288 | 289 | if (!Modifier.isVolatile(modifiers)) 290 | throw new IllegalArgumentException("Must be volatile type"); 291 | 292 | this.cclass = (Modifier.isProtected(modifiers) && 293 | caller != tclass) ? caller : null; 294 | this.tclass = tclass; 295 | offset = unsafe.objectFieldOffset(field); 296 | } 297 | 298 | private void fullCheck(T obj) { 299 | if (!tclass.isInstance(obj)) 300 | throw new ClassCastException(); 301 | if (cclass != null) 302 | ensureProtectedAccess(obj); 303 | } 304 | 305 | public boolean compareAndSet(T obj, long expect, long update) { 306 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 307 | return unsafe.compareAndSwapLong(obj, offset, expect, update); 308 | } 309 | 310 | public boolean weakCompareAndSet(T obj, long expect, long update) { 311 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 312 | return unsafe.compareAndSwapLong(obj, offset, expect, update); 313 | } 314 | 315 | public void set(T obj, long newValue) { 316 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 317 | unsafe.putLongVolatile(obj, offset, newValue); 318 | } 319 | 320 | public void lazySet(T obj, long newValue) { 321 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 322 | unsafe.putOrderedLong(obj, offset, newValue); 323 | } 324 | 325 | public long get(T obj) { 326 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 327 | return unsafe.getLongVolatile(obj, offset); 328 | } 329 | 330 | private void ensureProtectedAccess(T obj) { 331 | if (cclass.isInstance(obj)) { 332 | return; 333 | } 334 | throw new RuntimeException( 335 | new IllegalAccessException("Class " + 336 | cclass.getName() + 337 | " can not access a protected member of class " + 338 | tclass.getName() + 339 | " using an instance of " + 340 | obj.getClass().getName() 341 | ) 342 | ); 343 | } 344 | } 345 | 346 | 347 | private static class LockedUpdater extends AtomicLongFieldUpdater { 348 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 349 | private final long offset; 350 | private final Class tclass; 351 | private final Class cclass; 352 | 353 | LockedUpdater(Class tclass, String fieldName) { 354 | Field field = null; 355 | Class caller = null; 356 | int modifiers = 0; 357 | try { 358 | field = tclass.getDeclaredField(fieldName); 359 | caller = sun.reflect.Reflection.getCallerClass(3); 360 | modifiers = field.getModifiers(); 361 | sun.reflect.misc.ReflectUtil.ensureMemberAccess( 362 | caller, tclass, null, modifiers); 363 | sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 364 | } catch (Exception ex) { 365 | throw new RuntimeException(ex); 366 | } 367 | 368 | Class fieldt = field.getType(); 369 | if (fieldt != long.class) 370 | throw new IllegalArgumentException("Must be long type"); 371 | 372 | if (!Modifier.isVolatile(modifiers)) 373 | throw new IllegalArgumentException("Must be volatile type"); 374 | 375 | this.cclass = (Modifier.isProtected(modifiers) && 376 | caller != tclass) ? caller : null; 377 | this.tclass = tclass; 378 | offset = unsafe.objectFieldOffset(field); 379 | } 380 | 381 | private void fullCheck(T obj) { 382 | if (!tclass.isInstance(obj)) 383 | throw new ClassCastException(); 384 | if (cclass != null) 385 | ensureProtectedAccess(obj); 386 | } 387 | 388 | public boolean compareAndSet(T obj, long expect, long update) { 389 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 390 | synchronized (this) { 391 | long v = unsafe.getLong(obj, offset); 392 | if (v != expect) 393 | return false; 394 | unsafe.putLong(obj, offset, update); 395 | return true; 396 | } 397 | } 398 | 399 | public boolean weakCompareAndSet(T obj, long expect, long update) { 400 | return compareAndSet(obj, expect, update); 401 | } 402 | 403 | public void set(T obj, long newValue) { 404 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 405 | synchronized (this) { 406 | unsafe.putLong(obj, offset, newValue); 407 | } 408 | } 409 | 410 | public void lazySet(T obj, long newValue) { 411 | set(obj, newValue); 412 | } 413 | 414 | public long get(T obj) { 415 | if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 416 | synchronized (this) { 417 | return unsafe.getLong(obj, offset); 418 | } 419 | } 420 | 421 | private void ensureProtectedAccess(T obj) { 422 | if (cclass.isInstance(obj)) { 423 | return; 424 | } 425 | throw new RuntimeException( 426 | new IllegalAccessException("Class " + 427 | cclass.getName() + 428 | " can not access a protected member of class " + 429 | tclass.getName() + 430 | " using an instance of " + 431 | obj.getClass().getName() 432 | ) 433 | ); 434 | } 435 | } 436 | } 437 | --------------------------------------------------------------------------------