synchronized

【Java并发工具类】Lock和Condition

和自甴很熟 提交于 2020-02-09 20:40:39
前言 Java SDK并发包通过 Lock 和 Condition 两个接口来实现管程,其中Lock用于解决互斥问题,Condition用于解决同步问题。我们需要知道,Java语言本身使用 synchronized 实现了管程的,那么为什么还在SDK中提供另外一种实现呢?欲知为何请看下文。 下面将先阐述再造管程的理由,然后详细介绍Lock和Condition,最后再看实现同步机制时是选择synchronized还是SDK中的管程。 再造管程的理由 Java本就从语言层面实现了管程,然而后面又在SDK中再次现实,这只能说明语言层面的实现的管程有所不足。要说谈synchronized的不足,我们就要要回顾一下 破坏死锁的不可抢占问题 : 破坏不可抢占条件,需要线程在获取不到锁的情况下主动释放它拥有的资源。当我们使用synchronized的时候,线程是没有办法主动释放它占有的资源的。因为,synchronized在申请不到资源时,会使线程直接进入阻塞状态,而线程进入了阻塞状态就不能主动释放占有的资源。 所以,有没有一种办法可以使得线程处于阻塞状态时也能够响应中断主动释放资源或者获取不到资源的时候不阻塞呢?答案是有的,使用SDK中的管程。 SDK中管程的实现 java.util.concurrent 中的 Lock 接口,提供了如下三种设计思想都可以解决死锁的不可抢占条件: 能够响应中断

火车票售票1

给你一囗甜甜゛ 提交于 2020-02-09 19:14:00
synchronized在多线程中的使用 先看一个例子: //模仿火车售票系统,假设有4个售票点同时售票,我们可以把四个售票点定义为四个独立线程 class Test { public static void main(String[] args) { TestThread tt=new TestThread(); new Thread(tt).start(); //每一个售票点定义为一个独立的线程,共同卖出所有的票 new Thread(tt).start(); new Thread(tt).start(); new Thread(tt).start(); } } class TestThread implements Runnable { int ticket=10; //票数定义 public void run() { while(ticket>0) { System.out.println(Thread.currentThread().getName()+":ticket "+ticket+"is saling"); ticket--; } } } 运行结果为: Thread-0:ticket 10is saling Thread-0:ticket 9is saling Thread-0:ticket 8is saling Thread-0:ticket 7is

深入并发锁,解析Synchronized锁升级

六月ゝ 毕业季﹏ 提交于 2020-02-09 17:06:40
这篇文章分为六个部分,不同特性的锁分类,并发锁的不同设计,Synchronized中的锁升级,ReentrantLock和ReadWriteLock的应用,帮助你梳理 Java 并发锁及相关的操作。 一、锁有哪些分类 一般我们提到的锁有以下这些: 乐观锁/悲观锁 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面分别说明。 1、乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度,在Java和数据库中都有此概念对应的实际应用。 (1)乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。 乐观锁适用于多读的应用类型,乐观锁在Java中是通过使用无锁编程来实现,最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的。 CAS全称 Compare And Swap(比较与交换),是一种无锁算法。在不使用锁(没有线程被阻塞)的情况下实现多线程之间的变量同步。java.util.concurrent包中的原子类就是通过CAS来实现了乐观锁。 简单来说,CAS算法有3个三个操作数:

并发编程

自闭症网瘾萝莉.ら 提交于 2020-02-09 10:20:13
Synchronized 修饰类中的静态方法,与非静态方法。 话不多说直接上代码 1234567891011121314151617181920212223242526272829303132333435363738394041 public class MultiThread{ private static int num=0; public synchronized void printNum(String tag){ try{ if(tag.equals("a")){ num=100; System.out.println("tag a,set num over"); Thread.sleep(1000); }else{ num=200; System.out.println("tag b,set num over"); } System.out.println("tag"+tag+",num="+num); }catch(InterruptedException e){ e.printStackTrace(); } } public static void main(String[] args){ final MultiThread m1=new MultiThread(); final MultiThread m2=new MultiThread(); Thread t1

单线程与多线程介绍

雨燕双飞 提交于 2020-02-08 23:16:47
简单的说,单线程就是进程中只有一个线程。单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。 以上是main方法,是一个主线程。 多线程 由一个或者多个线程组成的程序就是多线程,Java中,一定是从主线程开始执行(main方法),然后在主线程的某个位置启动新的线程。 二、线程的基本操作 2.1 创建 创建线程的两种方法 1、继承java.lang.Thread 上述代码中,MyThread类继承了类java.lang.Thread,并覆写了run方法。主线程从main方法开始执行,当主线程执行至t.start()时,启动新线程(注意此处是调用start方法,不是run方法),新线程会并发执行自身的run方法。 2、实现java.lang.Runnable接口 Mythread通过实现Runnable接口,覆写了run方法,实现创建线程的过程,与继承Thread类创建的线程是一样的结果。实际Thread类里边也是通过实现Runnable接口,唯一不同的就是这里边的run方法是空的。里边具体的实现交由外层调用类采用override实现。 注意事项:多线程的运行过程中,如果主线程已经执行完成,但是其子线程还在执行,那表明程序还未结束,等到所有的线程都执行完成时,程序才算结束。 2.2 暂停 线程中的暂停操作是调用sleep实现的

并发编程之线程第二篇

北慕城南 提交于 2020-02-08 22:50:00
并发编程之线程第二篇 3.12 五种状态 3.13 六种状态 4.1 共享带来的问题 4.2 synchronized解决方案 4.4 变量的线程安全分析 4.6 Monitor概念 1. 轻量级锁 2. 锁膨胀 3.12 五种状态 这是从操作系统层面来描述的 【初始状态】仅是在语音层面创建了线程对象,还未与操作系统线程关联 【可运行状态】(就绪状态)指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行 【运行状态】指获取了CPU时间片运行中的状态 (1)当CPU时间片用完,会从【运行状态】转换至【可运行状态】,会导致线程的上下文切换 【阻塞状态】 (1)如果调用了阻塞API,如BIO读写文件,这时该线程实际不会用到CPU,会导致线程上下文切换,进入【阻塞状态】 (2)等BIO操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】 (3)与【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们 【终止状态】表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态 3.13 六种状态 这是从Java API层面来描述的 根据Thread.State枚举,分为六种状态 NEW 线程刚被创建,但是还没有调用start()方法 RUNNABLE 当调用了start()方法之后,注意,Java

synchronized的可重入怎么实现的

邮差的信 提交于 2020-02-08 22:28:24
● 请说明一下synchronized的可重入怎么实现。 考察点:锁 参考回答: 每个锁关联一个线程持有者和一个计数器。当计数器为0时表示该锁没有被任何线程持有,那么任何线程都都可能获得该锁而调用相应方法。当一个线程请求成功后,JVM会记下持有锁的线程,并将计数器计为1。此时其他线程请求该锁,则必须等待。而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增。当线程退出一个synchronized方法/块时,计数器会递减,如果计数器为0则释放该锁。 来源: CSDN 作者: 学亮编程手记 链接: https://blog.csdn.net/a772304419/article/details/104226398

40个Java多线程问题总结

▼魔方 西西 提交于 2020-02-08 22:14:31
前言 这些多线程的问题,有些来源于各大网站、有些来源于自己的思考。可能有些问题网上有、可能有些问题对应的答案也有、也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不吝指教。 1、多线程有什么用? (1)发挥多核CPU的优势 随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。 (2)防止阻塞 从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题

解决线程安全的三种方法

点点圈 提交于 2020-02-08 13:30:52
1:线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 我们通过一个案例,演示线程的安全问题: 电影院要卖票,我们模拟电影院的卖票过程。假设要播放的电影是 “上海堡垒”,本次电影的座位共50个(只能卖50张票)。 我们来模拟电影院的售票窗口,实现多个窗口同时卖 “葫芦娃大战奥特曼”这场电影票(多个窗口一起卖这50张票)需要窗口,采用线程对象来模拟;需要票, Runnable 接口子类来模拟 模拟买票 : public class Ticket implements Runnable { private int ticket = 50; /* *执行卖票操作 */ @Override public void run() { //每个窗口卖票的操作 //窗口 永远开启 while (true) { if (ticket > 0) {//有票 可以卖 //出票操作 //使用sleep模拟一下出票时间 try {Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } //获取当前线程对象的名字 String name = Thread.currentThread()

Java_多线程基础

馋奶兔 提交于 2020-02-08 12:44:54
自定义线程 实现方式 继承Thread类 实现Runnable 接口 继承Thread 类 继承Thread后,要重写run 方法 public void run 方法体 为该线程要执行的任务 启动线程的方法为 start() ,不是调用run() 调用run方法不能开启新的线程,只是普通的函数调用 线程的生命周期类只能被启动一次 public class xiancheng2 { public static void main(String[] args) { //创建对象 Myrun run1 = new Myrun(); //创建线程对象 Thread runTd = new Thread( run1 ); // 开启线程 runTd.start(); run1.say(); } } class Myrun extends Thread{ @Override public void run() { System.out.println("新的线程"); } public void say() { System.out.println( "美好的一天" ); } } 常用API String getName() 返回该线程的名称。 long getId() 返回该线程的标识符。 int getPriority() 返回线程的优先级。 Thread.State getState(