synchronized实现线程同步

多线程访问同一个变量时,如果这些线程中既有读操作,又有写操作,就会导致变量值出现混乱。这个时候应该实现线程同步。
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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值