java并发(2):synchronized 的理解

synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入临界区,同时他还可以保证共享变量的内存可见性。

synchronized同步关键字,主要用法有同步方法,同步代码块,

主要理解几句话:

1)当一个线程正在访问一个对象的synchronized方法,那么其他线程不能访问该对象的其他synchronized方法,因为一个对象只有一个锁,当一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁。

2)当一个线程正在访问一个对象的synchronized方法,那么其他线程能访问该对象的非synchronized方法,因为访问非synchronized方法不需要获得该对象的锁。

3)如果一个线程A需要访问对象object1的synchronized方法fun1,另外一个线程B需要访问对象boject2的synchronized方法fun1,即使object1和object2是同一个类型(一个类new出来两个对象),也不会产线程安全问题,因为访问的不是同一个对象。

 

第一种:package com.ucmed.zsyy.util;

public class DirtyRead {

    private String username = "zjkj";

    private String password = "123";

    public synchronized void setValue(String username, String password) {

        System.out.println("set线程:" + Thread.currentThread().getPriority());

        this.username = username;

        try {

            Thread.sleep(2000);

        } catch(InterruptedException e) {

            e.printStackTrace();

        }

        this.password = password;

        System.out.println("setValue最终结果:username = " + username + "  , password = " + password);

    }

    public void getValue() {

        System.out.println("get线程:" + Thread.currentThread().getPriority());

        System.out.println("getValue最终结果:username = " + username + "  , password = " + password);

    }

    public static void main(String[] args) throws InterruptedException {

        final DirtyRead dr = new DirtyRead();

        Thread t1 = new Thread(new Runnable() {

            @Override

            public void run() {

                dr.setValue("z3", "456");

            }

        });

        System.out.println("主线程:" + Thread.currentThread().getPriority());

        t1.start();

        Thread.sleep(1000);

        dr.getValue();

    }

}

第二种:

package com.ucmed.zsyy.util;

public class DirtyRead {

    private String username = "zjkj";

    private String password = "123";

    public synchronized void setValue(String username, String password) {

        System.out.println("set线程:" + Thread.currentThread().getPriority());

        this.username = username;

        try {

            Thread.sleep(2000);

        } catch(InterruptedException e) {

            e.printStackTrace();

        }

        this.password = password;

        System.out.println("setValue最终结果:username = " + username + "  , password = " + password);

    }

    public synchronized void getValue() {

        System.out.println("get线程:" + Thread.currentThread().getPriority());

        System.out.println("getValue最终结果:username = " + username + "  , password = " + password);

    }

    public static void main(String[] args) throws InterruptedException {

        final DirtyRead dr = new DirtyRead();

        Thread t1 = new Thread(new Runnable() {

            @Override

            public void run() {

                dr.setValue("z3", "456");

            }

        });

        System.out.println("主线程:" + Thread.currentThread().getPriority());

        t1.start();

        Thread.sleep(1000);

        dr.getValue();

    }

}

4)理解:

这里只有一个对象,一个对象的多个synchronized修饰的方法的情况

上面例子是当get方法加上锁后,要等待set方法执行完后再执行

在方法上加synchronized关键字,持有的锁为当前对象,当一个线程调用了其中一个synchronized的方法后,其他线程再调用该类中其他synchronized修饰的方法会挂起等待,需要等上一个线程执行完,释放锁后,其他调用线程取得锁后才会执行

不是多个锁,是多个synchronized修饰的方法..这些方法是同一个锁

5):一个线程执行一个对象的非static synchronized方法,另外一个线程执行这个对象的static synchronized方法,此时不会发生互斥现象,因为static synchronized占用的是类锁,而非static synchronized方法占用的是对象锁,所以不会互斥。(我的理解:static是不需要new对象的,所以是用类锁,而非static是需要new 一个对象出来的,说以是对象锁)

注意:对于synchronized,当出现异常的时候,jvm都会自动释放当前线程占用的锁,所以异常不会导致死锁。

锁的原理及优化锁:http://cmsblogs.com/?p=2071

锁优化:锁主要的四种状态:无锁,偏向锁,轻量级锁,重量级锁,依次升级,但不能降级,是为了提高获得锁和释放锁的效率

 偏向锁和轻量级锁的过程基本都是,检测Mark Word,然后标记,然后CAS竞争,修改标记,最后释放

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值