线程基础一

     工作之余补充一下线程方面的知识。直接上源码:

   

package cn.qxp.test;

/**
 * 此线程会出现脏读的情况。即输出结果有可能是两个800,或者两个100.
 * 
 * 原因:th和th2是SyncThread两个不同的对象实例,
 *             在todo中的synchronized同步检查的目标是不一样的。
 * 
 *            要特别注意synchronized检查是目标
 * @author Administrator
 *
 */
public class SyncThread implements Runnable{
    
    private  Integer value;
    
    private static Integer NOWVALUE;

    public SyncThread(Integer value) {
        this.value = value;
    }
    
//---------------------------------------------------------------------------------------------------
    /* 脏读写法1。
     * 这是同步方法,检查的目标是当前对象实例,由于new了两个对象实例,当后面的线程执行到这里时,并不会进行检查。
     * 
     * 当线程1执行到NOWVALUE = this.value,value=100时,在执行打印语句之前,
     * 线程2也刚好执行到NOWVALUE = this.value,这是就会打印出两个100。脏读出现
     * 
     * */
    /*private synchronized void todo() {
            NOWVALUE = this.value;
            System.out.println("NOWVALUE==="+NOWVALUE);
            
    }
    */
    
//---------------------------------------------------------------------------------------------------
    
    /*    
     * 脏读写法2。
     * 这是同步方法加同步代码快,this检查的也是当前的对象实例
     * 出现脏读的原因与上基本一致
     * 
     */
    /*private synchronized void todo() {
        synchronized (this) {
            NOWVALUE = this.value;
            System.out.println("NOWVALUE==="+NOWVALUE);
        }
    }*/
    
//---------------------------------------------------------------------------------------------------
    
    /* 
     * 不会出现脏读的写法。
     * 同步代码块中,检查的是SyncThread.class。
     * 表示对SyncThread这个类的所有实例进行检查。
     * 只要是SyncThread的实例。在执行到synchronized都会进行检查,
     * 若没有其他线程在synchronized里面,则执行。若有则等待正在执行的释放对象锁,抢占执行权
     * 
     */
    private  void todo() {
        synchronized (SyncThread.class) {
            NOWVALUE = this.value;
            System.out.println("NOWVALUE==="+NOWVALUE);
        }
    }

//---------------------------------------------------------------------------------------------------    
    @Override
    public void run() {
        
        this.todo();
    }
    
    public static void main(String[] args) {
        
        Thread th = new Thread(new SyncThread(100));
        Thread th2 = new Thread(new SyncThread(800));
        
        th.start();
        th2.start();
    }
}

    总结:

 判断一个对象是否线程安全,除了synchronized 之外,更重要的是synchronized锁的目标。

在脏读写法1中,非静态方法上加锁。synchronized锁的目标是:当前对象的todo方法。若非当前对象,则锁无效。使用new创建了一个全新的对象实例,非当前对象。

脏读写法2中,synchronized(this){},锁的目标也是当前对象(this指代的是当前对象),

非脏读写法中,synchronized(SyncThread.class){},锁的目标是SyncThread类是class对象,SyncThread的所有实例对象进行同步锁检查。

静态方法上加锁,private static synchronized void todo(){}这种写法,与synchronized(SyncThread.class){}写法非常类似。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值