Java多线程 - 对象及变量的并发访问

1. synchronized同步方法
多个线程调用synchronized声明的方法一定是排队执行的。而且只有共享资源的读写访问才需要同步化,如果不是共享资源,那根本没有同步的必要。
(1)脏读
多线程调用同一个实例对象的同一个方法时,为了避免数据不同步的出现,使用了synchronized关键。
虽然在赋值的方法上做了同步,但是再取值的方法上没有做同步,取值了的时候出现了意象不到的情况,这就是脏读(dirtyRead)。脏读的情况发生在读取变量的时候,此值已经被其他线程修改了。
(2)锁重入
关键字synchronized具有锁重入的功能。就是在使用synchronized的时候,当一个线程得到一个对象锁后,再次请求该对象锁时是可以得到该多想的锁的。这也说明在一个synchronized方法/块内调用本类的其他synchronized方法/块时,是永远可以得到锁的。
“可重入锁”的概念是:自己可以再次获得自己的内部锁。当一个线程获得了某个对象的锁之后,此时这个锁对象还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的。如果不可以锁重入的话,就会造成死锁。
可重入锁也支持在父子继承的环境中:

public class Main {

    public int i = 5;

    synchronized public void mainPrint() {
        i --;
        System.out.println("i=" + i);
    }
}
public class ThreadTest extends Main{

    synchronized public void testPrint() {
        while(i > 0) {
            i --;
            System.out.println("i="+i);
        }
    }

    public static void main(String[] args) {

        Thread thread = new Thread(){
            @Override
            public void run() {
                new ThreadTest().testPrint();
            }
        };
        thread.start();
    }
}

输出结果:

i=4
i=3
i=2
i=1
i=0

此例子说明,当存在子父类继承关系时,子类完全可以通过“可重入锁”调用父类的同步方法。(注意是同一个锁才可以)
(3)同步方法或代码块出现异常时,所持有的锁自动释放。
(4)同步不具有继承性,就是说父类的同步方法如果被子类重写,如果子类重写的时候非同步,那么通过子类类型实例调用该方法时,不同步。

2. 同步代码块
使用同步方法有时候是有弊端的。比如一个线程调用同步方法执行一个比较耗时的任务,那么其他线程必须等待较长时间。这样的情况可以使用同步代码块来解决。
两个线程访问同一个对象中的synchronized(this)同步代码块时,一段时间内只能被一个线程执行,另个线程只能等到当前线程执行完这段代码后才能继续执行。
多个线程调用同一个对象的不同名称的synchronized方法或者synchronized(this)代码块的时候,调用效果就是按顺序执行的。因为this代表该对象,而同步方法的锁也是该对象。
(1)静态同步synchronized方法与synchronized(class)代码块。
关键字synchronized可以加在静态方法,如果这样写,是对当前.java文件对应的Class类进行持锁。Class锁可以对类的所有对象实例起作用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值