Java util.concurrent包AtomicXXX系列对象在C#中的实现

(本文作者温少,首发于博客园,转载请注明)

从JDK 1.5开始,util.concurrent包提供了Atomic类型,包括AtomicInteger、AtomicLong、AtomicBoolean、AtomicReference、AtomicFieldUpdate等,这些类在并发编程中大有作用。

我原先以为JDK中的Atomic在Windows下实现是调用<windows.h>中InterLockedXXX系列函数实现的,但后来查看了JDK的源码,发现和原先想像中的不一样。JVM的实现中,封装了一个Atomic的类,然后不同的操作系统有不同的实现,例如,在JDK 1.6源码hotspot\src\os_cpu\win32_i486\vm\atomic_win32_i486.inline.hpp文件中:

inline jlong    Atomic::cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value) {
  
int mp = os::is_MP();
  jint ex_lo  
= (jint)exchange_value;
  jint ex_hi  
= *( ((jint*)&exchange_value) + 1 );
  jint cmp_lo 
= (jint)compare_value;
  jint cmp_hi 
= *( ((jint*)&compare_value) + 1 );
  __asm {
    push ebx
    push edi
    mov eax, cmp_lo
    mov edx, cmp_hi
    mov edi, dest
    mov ebx, ex_lo
    mov ecx, ex_hi
    LOCK_IF_MP(mp)
    cmpxchg8b qword ptr [edi]
    pop edi
    pop ebx
  }
}

C#也提供了同样的能力,System.Threading.Interlocked封装了<windows.h>中的 InterlockedXXX系列函数,可以实现同样的功能,但是直接使用InterLocked没有象Java中的Atomic系列对象方便。

了解清楚Java中的AtomicXXX和.NET中InterLockedXXX系列函数之后,把Java的AtomicXXX系列对象在C#上重新实现一遍是很容易的事情。例如实现AtomicInteger:

public class AtomicInteger
{
    
private int value;

    
public AtomicInteger(int initialValue)
    {
        value 
= initialValue;
    }

    
public AtomicInteger()
        : 
this(0)
    {
    }

    
public int Get()
    {
        
return value;
    }

    
public void Set(int newValue)
    {
        value 
= newValue;
    }

    
public int GetAndSet(int newValue)
    {
        
for (; ; )
        {
            
int current = Get();
            
if (CompareAndSet(current, newValue))
                
return current;
        }
    }

    
public bool CompareAndSet(int expect, int update)
    {
        
return Interlocked.CompareExchange(ref value, update, expect) == expect;
    }

    
public int GetAndIncrement()
    {
        
for (; ; )
        {
            
int current = Get();
            
int next = current + 1;
            
if (CompareAndSet(current, next))
                
return current;
        }
    }

    
public int GetAndDecrement()
    {
        
for (; ; )
        {
            
int current = Get();
            
int next = current - 1;
            
if (CompareAndSet(current, next))
                
return current;
        }
    }

    
public int GetAndAdd(int delta)
    {
        
for (; ; )
        {
            
int current = Get();
            
int next = current + delta;
            
if (CompareAndSet(current, next))
                
return current;
        }
    }

    
public int IncrementAndGet()
    {
        
for (; ; )
        {
            
int current = Get();
            
int next = current + 1;
            
if (CompareAndSet(current, next))
                
return next;
        }
    }

    
public int DecrementAndGet()
    {
        
for (; ; )
        {
            
int current = Get();
            
int next = current - 1;
            
if (CompareAndSet(current, next))
                
return next;
        }
    }

    
public int AddAndGet(int delta)
    {
        
for (; ; )
        {
            
int current = Get();
            
int next = current + delta;
            
if (CompareAndSet(current, next))
                
return next;
        }
    }

    
public override String ToString()
    {
        
return Convert.ToString(Get());
    }
}

封装过之后,直接使用AtomicInteger比使用InterLocked更方便,代码也会更直观优美!

(本文作者温少,首发于博客园,转载请注明)

posted on 2007-11-15 05:52  温少  阅读(3678)  评论(6编辑  收藏  举报

导航