加入收藏 | 设为首页 | 会员中心 | 我要投稿 葫芦岛站长网 (https://www.0429zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Java高并发编程分析

发布时间:2021-12-07 16:25:31 所属栏目:教程 来源:互联网
导读:一、同步锁 1.synchronized关键字(互斥锁) 对某个对象加锁,任何线程要执行锁后面的代码,必须要先拿到对象的锁 2.synchronized的使用方法 1)synchronized(this),任何线程要执行锁后的代码,必须要先拿到this的锁 2)在方法上加上synchronized关键字,等

一、同步锁
 
  1.synchronized关键字(互斥锁)
 
    对某个对象加锁,任何线程要执行锁后面的代码,必须要先拿到对象的锁
 
  2.synchronized的使用方法
 
    1)synchronized(this),任何线程要执行锁后的代码,必须要先拿到this的锁
 
    2)在方法上加上synchronized关键字,等同于在方法执行时加上synchronized(this)
 
    3)当synchronized用在静态方法上时,等同于synchronized(包名.类名.class)
 
    4)在静态方法中使用同步锁,等同于synchronized(类名.class)
 
  3.同步锁的各种情形
 
    1)在一个加锁的方法执行过程中,可以执行另外非加锁的方法
 
    2)一个同步方法可以调用另一个同步方法
 
    3)一个线程已经拥有某个对象的锁,再次申请时仍然会得到该对象的锁,也就是说synchronized的锁是可重入的(相当于在锁上加了个数字,从1~2,synchronized具有重入性)
 
    4)继承中可能发生的情形:子类调用父类的同步方法,锁定的是同一个对象
 
    5)程序在执行的过程中如果出现异常,默认情况下会释放锁,在第一个线程中抛出异常,其他线程就会进入同步代码块,有可能会访问到异常产生的数据
 
  4.synchronized的特性
 
    原子性、可见性、重入性(不是主要特性)
 
  二、无锁同步
  1.volatile关键字,使一个变量再多个线程间可见
 
  2.理解volatile的作用需要用到JMM(Java Memory Model)java内存模型
 
    cpu也可以是线程的缓冲区将主内存中的内容读取过来,在缓冲区进行修改后再写回主内存,一开始cpu会将主内存内容copy一份到自己的缓冲区,在cpu开始处理后,可能不会有空闲时间读取主内存中的内容,而是直接读取自己缓冲区中的内容,而其他线程可能会对主内存中的内容进行修改,这样之前线程中存放的内容就是过期内容,但当我们在变量前使用了volatile关键字修饰后,当我们再去更改主内存中的变量后,主内存会通知其他线程缓冲区中的内容已过期,需要再去主内存中读取一遍,因此也就做到了无所也能数据同步
 
  3.volatile的特性
 
    可见性 
 
  三、volatile与synchronized的区别
  1.volatile本质是在告诉JVM当前变量在寄存器中的值是不确定的,需要从主内存中读取,而synchronized则是锁定当前对象,只有当前线程可以访问该对象,其他线程被阻塞
 
  2.volatile仅能使用在变量级别,synchronized则可以使用在变量方法上
 
  3.volatile仅能实现变量的修改可见性,但是不具备原子性,而synchronized既具备可见性又具备原子性
 
  4.synchronized相较于volatile更重一些,volatile的效率较synchronized要高
 
  四、AtomicXXX原子类
  1.如果只是处理简单的数字运算可以使用原子类来解决(如AtomicInteger等)  
 
  2.类本身的方法都是原子性的,但不能保证多个方法的连续调用是原子性的
 
  五、使用锁的技巧
  1.使用细粒度的锁更加有效率
 
  2.锁定对象o,如果对象o的属性发生改变,不影响锁的使用,但是如果o变成了另外一个对象,则锁的对象也会发生改变
 
  3.锁的信息记录在堆内存
 
  4.不要以字符串常量作为锁定对象,可能会产生莫名其妙的错误
 
  六、wait和notify
  1.wait会释放锁,notify不会释放锁
 
  2.使用wait和notify时必须要对对象锁定,调用被锁定对象的wait方法,只有调用notify方法才会启动正在这个对象上等待的线程
 
  3.notifyAll是启动所有在对象上等待的线程
 
  七、门闩Latch
  1.当不涉及同步只涉及线程通信时,用synchronized+wait和notify就显得太重了,这时应该考虑CountDownLatch/cyclibarrier/semaphore
 
  2.CountDownLatch不涉及锁,当Count的值为0时当前线程继续运行,使用await和countDown方法来代替wait和notify
 
    CountDownLatch latch = new CountDownLatch(1);//传入参数1减到0时当前线程继续运行
 
    latch.countDown();//latch的值减去1,等于0时闩打开
 
  3.使用Latch替代waithenotify来进行通知,好处是通信方式简单,同时可以指定等待时间
 
  附加:
  使用匿名内部类创建线程
 
  1.new Thread(){
 
    public void run(){}
 
   }.start();
 
  2.new Thread(new Runnable(){
 
    public void run(){}
 
   }).start();
 
  3.new Thread(new Callable(){
 
    public void call(){}
 
   }).start();

(编辑:葫芦岛站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!