synchronized实现线程同步

来源:互联网 发布:快牙mac版 编辑:程序博客网 时间:2024/04/29 19:00

多线程访问同一个变量时,如果这些线程中既有读操作,又有写操作,就会导致变量值出现混乱。这个时候应该实现线程同步。
synchronized是Java关键字,利用这个关键字可以做到线程同步。

synchronized修饰方法

synchronized用来修饰一个方法时,该方法称为同步方法。对于同一个对象,如果多个线程同时访问其同步方法,同一时刻只有一个线程能获取到该对象的锁,从而执行该同步方法。Hashtable是Java中线程同步的容器,其内部的方法很多都是加了synchronized关键字的。来看看get方法:

public synchronized V get(Object key) {       int hash = Collections.secondaryHash(key);        HashtableEntry<K, V>[] tab = table;        for (HashtableEntry<K, V> e = tab[hash & (tab.length - 1)];                e != null; e = e.next) {            K eKey = e.key;            if (eKey == key || (e.hash == hash && key.equals(eKey))) {                return e.value;            }        }        return null;    }

synchronized修饰静态方法

synchronized也可以用来修饰静态方法,注意其与直接修复普通方法的区别。修饰静态方法时,不管这个静态方法的类有多少个实例,一次只有一个线程能访问这个静态方法。而修饰普通方法时,每个实例都拥有自己的对象锁,不同实例的同步方法互不影响。

使用懒汉模式的单例时用到的就是synchronized修饰静态方法

  public class Singleton {          private Singleton() {}          private static Singleton instance;          public static synchronized Singleton getInstance() {            if (instance == null) {              instance = new Singleton();            }            return instance;          }        } 

synchronized修饰代码块

synchronized修饰方法时,整个方法都被同步了。由于同步会影响程序性能,所以同步的代码越少越好,这个时候就可以用synchronized同步代码块了。synchronized同步代码块时需要一个参数,这个参数可以是一个实例,也可以是所属类。

一般情况下,可以直接使用this来同步代码块,Picasso的LruCache就是这种方式:

   @Override public Bitmap get(String key) {        if (key == null) {          throw new NullPointerException("key == null");        }        Bitmap mapValue;        synchronized (this) {          mapValue = map.get(key);          if (mapValue != null) {            hitCount++;            return mapValue;          }          missCount++;        }        return null;      }

当然,也可以用一个实例化的变量,Android中Message使用一个实例变量来作为同步参数:

private static final Object sPoolSync = new Object();    public static Message obtain() {            synchronized (sPoolSync) {                if (sPool != null) {                    Message m = sPool;                    sPool = m.next;                    m.next = null;                    m.flags = 0; // clear in-use flag                    sPoolSize--;                    return m;                }            }            return new Message();        }

在static方法中,也可以直接用所属类来作为同步参数,如:

public class MyClass {        public static void log(String msg1, String msg2){           synchronized(MyClass.class){              log.writeln(msg1);              log.writeln(msg2);             }        }      }
0 0
原创粉丝点击