当前位置: 首页 > news >正文

甜品店网站建设营销型网站的目标是

甜品店网站建设,营销型网站的目标是,互联网保险的优缺点,网络运营者不得违反法律java锁一 多线程锁synchronized案例分析1.1synchronized介绍1.2 synchronized案例分析1.2.1.标准访问,请问先打印邮件还是短信?1.2.2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?分析1.2.3.新增⼀个普通⽅法hello(&…

java锁

  • 一 多线程锁synchronized案例分析
    • 1.1synchronized介绍
    • 1.2 synchronized案例分析
      • 1.2.1.标准访问,请问先打印邮件还是短信?
      • 1.2.2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?
        • 分析
      • 1.2.3.新增⼀个普通⽅法hello(),请问先打印邮件还是hello?
      • 1.2.4.两部⼿机,请问先打印邮件还是短信?
      • 1.2.5.两个静态同步⽅法,同⼀部⼿机,请问先打印邮件还是短信?
      • 1.2.6.两个静态同步⽅法,2部⼿机,请问先打印邮件还是短信?
      • 1.2.7.1个普通同步⽅法,1个静态同步⽅法,1部⼿机,请问先打印邮件还是短信?
      • 1.2.8.1个普通同步⽅法,1个静态同步⽅法,2部⼿机,请问先打印邮件还有短信?
      • 1.2.8 总结
  • 二⼈⼯窗⼝排队购票(回顾)
  • 三 公平锁⾮公平锁 (⽕⻋站⼈⼯窗⼝排队购票)
  • 四 可重⼊锁/递归锁
    • 锁的配对
  • 五 ⾃旋锁
  • 六 读写锁/独占/共享

一 多线程锁synchronized案例分析

1.1synchronized介绍

关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile使用方法

1.普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁
2.静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁
3.同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁

1.2 synchronized案例分析

使用8个案例来详细说明synchronized的加锁用法:

1.标准访问,请问先打印邮件还是短信?
2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?
3.新增⼀个普通⽅法hello(),请问先打印邮件还是hello?
4.两部⼿机,请问先打印邮件还是短信?
5.两个静态同步⽅法,同⼀部⼿机,请问先打印邮件还是短信?
6.两个静态同步⽅法,2部⼿机,请问先打印邮件还是短信?
7.1个普通同步⽅法,1个静态同步⽅法,1部⼿机,请问先打印邮件还是短信?
8.1个普通同步⽅法,1个静态同步⽅法,2部⼿机,请问先打印邮件还有短信?

1.2.1.标准访问,请问先打印邮件还是短信?

答案:邮件

class Phone {public synchronized void sendEmail() {System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}

1.2.2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?

答案:邮件

//2. 邮件方法暂停4秒钟,请问先打印邮件还是短信? 邮件
class Phone {public synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}

分析

普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁

⼀个对象⾥⾯如果有多个synchronized⽅法,某⼀个时刻内,只要⼀个线程去调⽤其中的⼀个synchronized⽅法了,其他的线程都只能等待。换句话说,某⼀个时刻内,只能有唯⼀⼀个线程去访问这些 synchronized⽅法,锁的是当前对象this(new 的这个phone),被锁定后,其他的线程都不能进⼊到当前对象的其他的synchronized⽅法。
在这里插入图片描述

1.2.3.新增⼀个普通⽅法hello(),请问先打印邮件还是hello?

答案:hello
加个普通⽅法后发现和同步锁⽆关
在这里插入图片描述

//3. 新增一个普通方法hello(),请问先打印邮件还是hello?
class Phone {public synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();new Thread(() -> {phone.hello();}, "t3").start();//sayHello//==========sendEmail//======sendMessage}
}

1.2.4.两部⼿机,请问先打印邮件还是短信?

答案:邮件
分析:换成两个对象后,不是同⼀把锁了,情况⽴刻变化

//4. 两部手机,请问先打印邮件还是短信?
class Phone {public synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();Phone phone2 = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone2.sendMessage();}, "t2").start();//======sendMessage//==========sendEmail}
}

1.2.5.两个静态同步⽅法,同⼀部⼿机,请问先打印邮件还是短信?

答案:邮件
分析:见 1.2.6

//5. 两个静态同步方法,同一部手机,请问先打印邮件还是短信?
class Phone {public static synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public static synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}

1.2.6.两个静态同步⽅法,2部⼿机,请问先打印邮件还是短信?

答案: 邮件
分析: 静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁
全局锁
在这里插入图片描述

//6. 两个静态同步方法,2部手机,请问先打印邮件还是短信?
class Phone {public static synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public static synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();Phone phone2 = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone2.sendMessage();}, "t2").start();//==========sendEmail//======sendMessage}
}

1.2.7.1个普通同步⽅法,1个静态同步⽅法,1部⼿机,请问先打印邮件还是短信?

答案: 短信
分析:
在这里插入图片描述

//7. 1个普通同步方法,1个静态同步方法,1部手机,请问先打印邮件还是短信?
class Phone {public  synchronized void sendEmail() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("==========sendEmail");}public static synchronized void sendMessage() {System.out.println("======sendMessage");}public void hello() {System.out.println("sayHello");}
}public class LockDemo {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sendEmail();}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {phone.sendMessage();}, "t2").start();//======sendMessage//==========sendEmail}
}

1.2.8.1个普通同步⽅法,1个静态同步⽅法,2部⼿机,请问先打印邮件还有短信?

答案: 短信
分析:

在这里插入图片描述

1.2.8 总结

(1)当⼀个线程试图访问同步代码块时,它⾸先必须得到锁,退出或抛出异常时必须释放锁。 也就是说如果⼀个实例对象的普通同步⽅法获取锁后,该实例对象的其他普通同步⽅法必须等待获取锁的⽅法释放锁后才能获取锁,可是别的实例对象的普通同步⽅法因为跟该实例对象的普通同步⽅法⽤的是不同的锁,所以⽆需等待该实例对象已获取锁的普通同步⽅法释放锁就可以获取他们⾃⼰的锁。
(2)所有的静态同步⽅法⽤的也是同⼀把锁–类对象本身, 这两把锁(this/class)是两个不同的对象,所以静态同步⽅法与⾮静态同步⽅法之间是 不会有静态条件的。 但是⼀旦⼀个静态同步⽅法获取锁后,其他的静态同步⽅法都必须等待该⽅法释放锁后才能获取锁,⽽不管是同⼀个实例对象的静态同步⽅法之间,还是不同的实例对象的静态同步⽅法之间,只要它们同⼀个类的实例对象

二⼈⼯窗⼝排队购票(回顾)

题目:三个售票员 卖出 30张票
多个线程共抢一个资源

/*** 题目:三个售票员   卖出   30张票**/
class Ticket{//资源类//票private int number = 30;public synchronized void saleTicket(){if (number > 0) {System.out.println(Thread.currentThread().getName()+"\t卖出第:"+(number--)+"\t还剩下:"+number);}}}public class SaleTicketDemo {public static void main(String[] args) {Ticket ticket = new Ticket();new Thread(()->{ for (int i = 1; i <= 30 ; i++) ticket.saleTicket(); }, "A").start();new Thread(()->{ for (int i = 1; i <= 30 ; i++) ticket.saleTicket(); }, "B").start();new Thread(()->{ for (int i = 1; i <= 30 ; i++) ticket.saleTicket(); }, "C").start();}
}

在这里插入图片描述
我们用synchronized同步代码块的方式来解决。随着juc并发编程。我们有更加轻量级的锁方式来解决问题。

三 公平锁⾮公平锁 (⽕⻋站⼈⼯窗⼝排队购票)

lcok锁

 Lock lock = new ReentrantLock();

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
概念
公平锁,就是多个线程按照申请锁的顺序来获取锁,类似排队,先到先得。
⾮公平锁,则是多个线程抢夺锁,会导致优先级反转或饥饿现象。
区别:

  • 公平锁在获取锁时先查看此锁维护的等待队列,为空或者当前线程是等待队列的队⾸,则直接占有锁,否则插⼊到等待队列,FIFO原则。
  • ⾮公平锁⽐较粗鲁,上来直接先尝试占有锁,失败则采⽤公平锁⽅式。⾮公平锁的优点是吞吐量⽐公平锁更⼤。

synchronizedjuc.ReentrantLock默认都是⾮公平锁ReentrantLock在构造的时候传⼊ true 则是公平锁

四 可重⼊锁/递归锁

在这里插入图片描述
可重⼊锁⼜叫递归锁指的同⼀个线程在外层⽅法获得锁时,进⼊内层⽅法会⾃动获取锁。也就是说,线程可以进⼊任何⼀个它已经拥有锁的代码块。
⽐如method01⽅法⾥⾯有method02⽅法,两个⽅法都有同⼀把锁,得到了method01的锁。就⾃动得到了method02的锁,就像有了家⻔的锁,厕所、书房、厨房就为你敞开了⼀样。可重⼊锁可以避免死锁的问题。
在这里插入图片描述


/*** 可重入锁/递归锁*/class PhonePlus implements Runnable{//Synchronized Testpublic synchronized void sendEmail(){System.out.println(Thread.currentThread().getName()+"\t"+"sendEmail");sendSMS();}public synchronized void sendSMS(){System.out.println(Thread.currentThread().getName()+"\t"+"sendSMS");}//ReenTrantLock TestLock lock = new ReentrantLock();public void method1(){lock.lock();try {System.out.println(Thread.currentThread().getName()+"\t"+"method1");method2();} finally {lock.unlock();}}public void method2() {lock.lock();try {System.out.println(Thread.currentThread().getName()+"\t"+"method2");} finally {lock.unlock();}}@Overridepublic void run() {method1();}
}public class ReentrantLockDemo {public static void main(String[] args) {PhonePlus phonePlus = new PhonePlus();new Thread(()->{phonePlus.sendEmail();}, "t1").start();new Thread(()->{phonePlus.sendEmail();}, "t2").start();Thread t3 = new Thread(phonePlus);Thread t4 = new Thread(phonePlus);t3.start();t4.start();}
}

锁的配对

锁之间要配对,加了⼏把锁,最后就得解开⼏把锁,下⾯的代码编译和运⾏都没有任何问题。但锁的数量不匹配会导致死循环。

lock.lock();
lock.lock();
try{someAction(); 
}finally{lock.unlock(); 
}

五 ⾃旋锁

所谓⾃旋锁,就是尝试获取锁的线程不会⽴即阻塞,⽽是采⽤循环的⽅式去尝试获取。⾃⼰在那⼉⼀直循环获取,就像“⾃旋”⼀样。这样的好处是减少线程切换的上下⽂开销,缺点是会消耗CPU。CAS底层的 getAndAddInt就是⾃旋锁思想。

//跟CAS类似,⼀直循环⽐较。
while (!atomicReference.compareAndSet(null, thread)) { }

在这里插入图片描述

/*** 题目:实现一个自旋锁* 自旋锁好处:循环比较获取直到成功为止,没有类似wait的阻塞。* <p>* 通过CAS操作完成自旋锁,A线程先进来调用myLock方法自己持有锁5秒钟,* B随后进来后发现当前有线程持有锁,不是null,所以只能通过自选等待,直到A释放锁后B随后抢到。*/
public class SpinLockDemo {//原子引用(线程)AtomicReference<Thread> atomicReference = new AtomicReference<>(); //Thread ==> null//获取锁public void myLock() {Thread currentThread = Thread.currentThread();System.out.println(Thread.currentThread().getName() + "\t com in...");while (!atomicReference.compareAndSet(null, currentThread)) {}}//释放锁public void myUnLock() {Thread currentThread = Thread.currentThread();atomicReference.compareAndSet(currentThread, null);System.out.println(Thread.currentThread().getName() + "\t unlock....");}public static void main(String[] args) {SpinLockDemo spinLockDemo = new SpinLockDemo();new Thread(() -> {spinLockDemo.myLock();try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}spinLockDemo.myUnLock();}, "AA").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {spinLockDemo.myLock();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}spinLockDemo.myUnLock();}, "BB").start();}
}

结果
在这里插入图片描述
过程分析
在这里插入图片描述

六 读写锁/独占/共享

读锁是共享的,写锁是独占的。 juc.ReentrantLocksynchronized都是独占锁,独占锁就是⼀个锁只能被⼀个线程所持有。有的时候,需要读写分离,那么就要引⼊读写锁,即 juc.ReentrantReadWriteLock

独占锁:指该锁⼀次只能被⼀个线程所持有。对ReentrantLockSynchronized⽽⾔都是独占锁
共享锁:指该锁可被多个线程所持有
ReenntrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是⾮常⾼效的,读写、写读、写写的过程是互斥的。

⽐如缓存,就需要读写锁来控制。缓存就是⼀个键值对,以下Demo模拟了缓存的读写操作,读的 get ⽅法使⽤了 ReentrantReadWriteLock.ReadLock(),写的 put⽅法使⽤了ReentrantReadWriteLock.WriteLock()。这样避免了写被打断,实现了多个线程同时读。

http://www.yayakq.cn/news/133796/

相关文章:

  • 高端网站哪个比较好阿里云服务器上做网站
  • 网站建设 技术团队机械加工图纸标注符号大全
  • 广州网站建设怎么样抖音代运营是做什么
  • 做网站的主流软件大冶seo网站优化排名推荐
  • vs网站开发源码汉中微信网站建设公司
  • 河北省廊坊市建设网站专业做相册书的网站
  • 包头教育云网站建设公司网站建站要多少钱一年
  • 怎么在百度上制作自己的网站建电子商务网站多少钱
  • 无锡制作网站公司哪家好营销自动化平台
  • 义乌网站建设联系方式网站怎么做一盘优化排名
  • 做招商类型的网站php开发网站优势
  • 网站推广与维护设计方案付费下插件wordpress
  • 做一个搜索引擎网站要多少钱做我女朋友网站p0rn视频
  • 论坛类网站开发报价网站开发语言为wap
  • 网站的内容建设中国建设业管理协会网站
  • 公司网站域名如何续费做移动网站优化软
  • 青岛网站建设机构软件工程四大方向
  • 广州建设网站哪家好51网页版在线登录入口
  • j2ee网站开发免费教程wordpress关闭手机访问不了
  • 街道网站建设网站应包括的基本功能和高级功能
  • 给网站写文章怎么做网站的最近浏览 怎么做
  • 网站开发的开发语言棋牌网站哪里做
  • 内网是怎么做网站的互联网行业都有哪些工作岗位呢
  • 建站网站破解版个人备案公司网站
  • 广州专业制作网站wordpress怎么导入产品
  • 杭州营销网站建设公司闵行区网站建设公司
  • 河北建设厅网站初始密码科技创新绘画作品
  • 网站开发的后台开发工具如何制作精美的ppt
  • 网络营销论文题目舟山seo网络优化招聘
  • 如何用文件传输协议登陆网站上海网站建设置作