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

html5商城网站模板网站开发 职位

html5商城网站模板,网站开发 职位,建设银行天津分行网站,做网站的开题报告怎么写一、线程安全 1.1 线程安全的概念 线程是随机调度执行的#xff0c;如果多线程环境下的程序运行的结果符合我们预期则说明线程安全#xff0c;反之#xff0c;如果遇到其他结果甚至引起了bug则说明线程不安全 1.2 经典例子与解释 下面举一个经典的线程不安全的例子… 一、线程安全 1.1 线程安全的概念 线程是随机调度执行的如果多线程环境下的程序运行的结果符合我们预期则说明线程安全反之如果遇到其他结果甚至引起了bug则说明线程不安全 1.2 经典例子与解释 下面举一个经典的线程不安全的例子 public class Demo2 {private static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 0; i 50000; i) {count;}});Thread t2 new Thread(() - {for (int i 0; i 50000; i) {count;}});t1.start();t2.start();t1.join();t2.join();System.out.println(count count);} }上述代码中t1和t2两个线程对count进行累加操作在主线程中启动这两个线程然后通过join等待这两个线程都执行完后打印count预期结果为100000但打印结果如下 上述结果不符合我们的预期这便是产生了线程安全问题 接下来我们通过CPU指令的方式解释上述原因 count这个行代码可以看作3个CPU指令 把内存count总的值读取到CPU寄存器中 load把寄存器中的值1此时任然在寄存器中 add把上述寄存器计算后的值写回到内存count里 save 由于线程随机调度所以两个线程的CPU指令执行顺序也是随机的。 例如下图 画图时间轴。。。。。。。。。。 首先t1线程和t2线程分别将1加载到CPU寄存器中假设此时count的值为1然后在寄存器中将其加1变为2最后t1先将2加载回内存中t2也把2加载回内存中所以两次加1操作只加了一次1 当然上述执行顺序只是无数可能中的一种可能t1的一组指令还没有执行完t2就执行了好几组 下面来总结一下线程不安全的原因 1.3 线程不安全的原因 线程是随机调度抢占式执行的修改共享数据多个线程修改同一个变量多个线程修改共享数据的操作不是原子性count是3个CPU指令但是赋值操作就是原子性的内存可见性问题指令重排序 4和5后面再解释 1.4 解决线程安全问题 根据上述原因下手 原因1无法干预 原因2可以干预但并不是一个普适的做法因为有些代码就是要修改同一个变量 原因3这是一个普适的做法我们可以将一系列非原子的操作打包成一个原子性的操作-加锁 1.4.1什么是锁 锁是在多线程编程中用来控制线程对共享资源访问的一种机制 1.针对锁主要有这两个操作 加锁线程t1加上锁之后t2也尝试使用同一个锁进行加锁就会阻塞等待 问什么叫“t2也尝试使用同一个锁进行加锁” 答你可以理解为我们给t2里的操作加上了一种机制这个机制就是必须加上锁才能进行操作t1拿了一个锁加锁后进行它的操作如果t2也想拿这个锁来加锁就必须等t1操作完成解锁之后再拿这个锁进行加锁进行它的操作在此之前t2要阻塞等待当然如果t2选择拿别的锁进行加锁就不会阻塞等待假设只有t1和t2两个线程 比如A在餐厅里定了一个包间把门上锁之后来用餐这样B来了就不会影响A用餐的过程也就是t2不会对t1修改count的过程进行干扰这样就保证了操作的原子性 解锁t1解锁之后t2才有可能拿到锁因为尝试竞争锁的线程可能不只一个 2. 锁的主要特性互斥一个线程获取到锁之后另一个线程也尝试加这个锁就会阻塞等待这种现象叫锁竞争或锁冲突代码中也可以有多个锁只有多个线程竞争同一个锁才会发生锁竞争竞争不同的锁则不会发生锁竞争 1.5 synchronized关键字 1.5.1 synchronized解读 使用synchronized关键字synchronized关键字解读 synchronized (locker) {count; } 这是一个Java的关键字不是方法synchronized后面括号里面写的是锁对象锁对象的用途用来区分两个线程是否针对同一个对象加锁如果是就会出现锁竞争/互斥就会引起阻塞等待如果不是就不会出现锁竞争也就不会阻塞等待 synchronized的{ }进入到代码块就是对上述锁对象进行加锁操作当出了代码块就是对锁对象进行解锁 我们可以让t1和t2都使用同一个锁对象locker来对count变量的修改操作进行上锁 private static int count 0; public static void main(String[] args) throws InterruptedException {Object locker new Object(); //锁对象Thread t1 new Thread(() - {for (int i 0; i 50000; i) {synchronized (locker) {count;}}});Thread t2 new Thread(() - {for (int i 0; i 50000; i) {synchronized (locker) {count;}}});t1.start();t2.start();t1.join();t2.join();System.out.println(count count); } 这样虽然两个线程仍然是抢占式执行的但是保证了count;这个操作的原子性结果为count 100000  Java中随便拿一个对象都可以作为加锁的对象 1.5.2 synchronized使用示例 1修饰代码块指定锁哪个对象也就是可以锁任意对象 public class SynchronizedDemo {private Object locker new Object();public void method() {synchronized (locker) {}} }锁当前对象()里直接写this public class SynchronizedDemo {public void method() {synchronized (this) {}} }2修饰普通方法锁的SynchronizedDemo对象谁调用method()方法就锁谁可以有多个 public class SynchronizedDemo {public synchronized void methond() {} } 3)修饰静态方法锁的SynchronizedDemo类对象一个java进程中一个类只有唯一一个类对象 public class SynchronizedDemo {public synchronized static void method() {} } 1.5.3 synchronized特性 1互斥 某个线程执行到某个对象的synchronized中时其他线程如果也执行到同一个对象synchronized就会阻塞等待 2可重入 for (int i 0; i 50000; i) {synchronized (locker) {synchronized (locker) {count;}} }上述线程先对locker进行第一次加锁在第二次加锁的时候locker对象已经被锁住了按照之前的理解尝试针对一个已经被锁的对象加锁时就会阻塞等待这种情况就叫死锁 但synchronized是可重入锁可重入锁的内部包含了线程持有者和计数器 如果某个线程加锁的时候发现这个锁已经被别人占用但是恰好占用的是自己那么仍然可以继续获取到锁并让计数器自增解锁的时候也就是每走出一个代码块计数器就会递减当减到0时才真正释放锁 这种机制就叫可重入锁 1.6 死锁 1.6.1 两个常见的场景 死锁有两个比较典型的场景 场景一不可重入锁引起的死锁 一个线程对一个线程连续加锁两次且这个锁是不可重入锁就会引起死锁 场景二两个线程两把锁 public static void main(String[] args) throws InterruptedException {Object locker1 new Object();Object locker2 new Object();Thread t1 new Thread(() - {synchronized(locker1) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (locker2) {System.out.println(t1获取了两把锁);}}});Thread t2 new Thread(() - {synchronized(locker2) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (locker1) {System.out.println(t2获取了两把锁);}}});t1.start();t2.start();System.out.println(死锁ing....);}上述代码中locker1被t1占用locker2被t2占用接下来t1需要locker2t2需要locker1这样就陷入了死锁 运行结果显示程序一直没有结束 1.6.2 如何避免死锁 死锁产生的四个必要条件 1锁具有互斥性 2锁不可抢占一个线程拿到锁之后除非它主动释放锁否则别人抢不走 以上这两点是锁的基本特性无法干预 3请求和保持一个线程拿到一把锁之后不释放这个锁的前提下在尝试获取其他锁嵌套加锁 解决方法就是不要让两个sychronized嵌套式的占用两个不同的锁对象进行加锁 4循环等待多个线程获取多个锁的过程中出现了循环等待A等待BB又等待A 这一点只要我们提前约定好获取锁的顺序即使出现了嵌套也不会引起死锁如下述代码t1和t2线程都先获取locker1再获取locker2这样就不会出现死锁 public static void main(String[] args) throws InterruptedException {Object locker1 new Object();Object locker2 new Object();Thread t1 new Thread(() - {synchronized(locker1) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (locker2) {System.out.println(t1获取了两把锁);}}});Thread t2 new Thread(() - {synchronized(locker1) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (locker2) {System.out.println(t2获取了两把锁);}}});t1.start();t2.start();} 任何一个死锁的场景都必须同时具备上述四点缺少一点都不会构成死锁 本篇文章到此结束下篇文章将继续对线程安全的知识进行讲解
http://www.dnsts.com.cn/news/168672.html

相关文章:

  • 西安做网站公司8只做男生穿搭的网站
  • 域名怎么绑定网站枞阳美好乡村建设办公窒网站
  • 做游戏网站公司wordpress前端页面模板
  • 韶关市手机网站建设怎么样制作网站的步骤有哪些
  • 深圳外贸网站定制wordpress设置文章第一张
  • 建站系统开发免费asp企业网站源码
  • 营销网站费用wordpress小工具页脚
  • 适合这手机浏览器主页的网站福州做彩票app网站
  • 学校网站用途龙之向导外贸官方网站
  • 好的网站2020三维动画设计
  • 做网站要和企业logo网站和网站的app
  • 广告联盟网站怎么做人工智能网页设计
  • 怎么自己做网站盗qq外贸网站建设免费
  • 网站论文参考文献做网站百度云
  • 浙江省2011年1月高等教育自学考试 网站建设与管理试题与答案破解版下载大全免费下载
  • 免费打开的网站南宁企业建站系统
  • 上海羽贝网站建设自响应式网站建设清单
  • 旅游手机网站建设沈阳市网站建设公司
  • 网站编程需要什么语言室内设计联盟网
  • 九江网站开发公司软件开发有用吗
  • 网站信息查询宁波正规seo推广公司
  • wordpress音乐网站主题客户提出网站建设申请
  • 保定网站建设设计公司免费开网店的app
  • 盈江城乡建设局网站中山工商注册公司
  • 装修案例朋友圈文案seo3立体构型
  • 旅游电子商务网站的建设方案wordpress音乐直链插件
  • 网站定制营销的过程微信营销软件功能
  • 轴承外贸网站怎么做网站后台加密
  • 深圳公司网站改版通知有网站地图的网站
  • 聊城住房和城乡建设部网站装饰公司网站源码下载