并发编程
文章平均质量分 67
Tomorrow YE
这个作者很懒,什么都没留下…
展开
-
《并发编程》--1.新建线程
新建线程需要使用new关键字创建一个线程对象,并且将它start()起来就行。Thread t = new Thread();t.start();线程t起来之后,有一个run()方法。start()方法就会新建一个线程并且让这个线程执行run()方法。单独调用run方法,只是普通的调用而已,如下Thread t = new Thread(){ @Override原创 2017-08-17 10:49:11 · 223 阅读 · 0 评论 -
《并发编程》--11.允许多个线程同时访问的信号量Semaphpre
信号量为多线程协作提供了更为强大的控制方法。广义上说,信号量是对锁的拓展。无论是内部所synchronized还是重入锁ReentrantLock,一次都只允许一个线程访问一块资源,而信号量却可以指定多个线程数,同时访问一个资源。信号量主要提供一下构造函数; public Semaphore(int permits) { sync = new NonfairSync(perm原创 2017-08-29 16:12:20 · 394 阅读 · 0 评论 -
《并发编程》--13.CountDownLatch和CyclicBarrier
CountDownLatch(倒计时器)指子线程所有执行完毕后,主线程继续执行。适应于火箭发射,发令枪响等。执行如下代码很容易理解public class countdown { public static void main(String[] args) { final CountDownLatch latch = new CountDownLa原创 2017-08-31 10:25:22 · 354 阅读 · 0 评论 -
《并发编程》--14.Java线程池和自定义线程
为了避免频繁的创建和销毁线程,减少CPU的压力,线程池就应运而生。newFixedThreadPool()方法:该方法返回一个只有一个线程的线程池,该线程池的数量是固定始终不变。当有新任务提交时,线程池中若有空闲线程,将会立即执行。若么有空闲线程,则会被暂存在任务队列中,待有空闲线程时,才能处理任务队列的任务。newSingleThreadExecutor()方法:该方法返回一个只有一原创 2017-08-31 11:19:22 · 244 阅读 · 0 评论 -
《并发编程》--15.线程安全的HashMap
众所周知,HashMap是线程不安全的。但是如果需要一个线程按钮的HashMap我们需要怎么做的。其中一个可行的办法就是Collections.synchronizedMap。如下代码就是线程安全的HashMappublic static Map m = Collections.synchronizedMap(new HashMap说白了,就是给HashMap加锁,jdk参考代码如下原创 2017-09-18 11:05:05 · 428 阅读 · 0 评论 -
《并发编程》--16.并发队列ConcurrentLinkedQueue
1.介绍在并发编程中需要使用线程安全的队列。如果我们要实现一个线程安全的队列有两种实现方式。a.使用阻塞算法, 使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。(不多赘述)b.使用非阻塞算法。 使用非阻塞的实现方式则可以使用循环CAS的方式来实现,本文让我们一起来研究下Doug Lea是如何使用非阻塞的方式来实现线程安原创 2017-09-26 11:21:04 · 210 阅读 · 0 评论 -
《并发编程》--17.BlockingQueue解析
1.BlockingQueue定义的常用方法 抛出异常特殊值阻塞超时插入add(e)offer(e)put(e)offer(e,time,unit)移除remove()poll()take()poll(time,unit)检查element()peek()不可用不可用原创 2017-09-26 11:57:38 · 231 阅读 · 0 评论 -
《并发编程》--18.Java层锁的优化
1 减少锁持有时间public synchronized void syncMethod(){ othercode1(); mutextMethod(); othercode2(); }像上述代码这样,在进入方法前就要得到锁,其他线程就要在外面等待。这里优化的一点在于,要减少其他线程等待的时间,所以,只用在有线程安全要求的程序上加锁public void sy原创 2017-09-26 16:01:10 · 200 阅读 · 0 评论 -
《并发编程》--19.虚拟机内的锁优化
首先要介绍下对象头,在JVM中,每个对象都有一个对象头。Mark Word,对象头的标记,32位(32位系统)。描述对象的hash、锁信息,垃圾回收标记,年龄还会保存指向锁记录的指针,指向monitor的指针,偏向锁线程ID等。简单来说,对象头就是要保存一些系统性的信息。1 偏向锁所谓的偏向,就是偏心,即锁会偏向于当前已经占有锁的线程 。大部分情况是没有竞争的(某个同步原创 2017-09-26 16:18:53 · 256 阅读 · 0 评论 -
《并发编程》--20.无锁的并发策略(比较交换 CAS)
与锁相比,使用比较交换(CAS)会使程序看起来更加复杂一些,但由于其非阻塞性,他对死锁天生免疫,并且,线程间的相互影响也远远比基于锁的方式要小。更为重要的是,使用无锁的方式完全没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销,因此,他要比基于锁的方式拥有更优越的性能。CAS算法的过程是这样:他包含三个参数CAS(V,E,N)。V表示要更新的变量,E表示预期值,N表示新值。当V值等于E值原创 2017-09-27 10:56:51 · 654 阅读 · 0 评论 -
《并发编程》--21.无锁的线程安全整数 AtomicInteger
JDK并发包下有一个atomic包,里面实现了一些直接中CAS操作的线程安全的类型。其中,最常用的一个类就是AtomicInteger。可以把它看做一个整数,但是与Integer不同的是,他是可变的,并且是线程安全的(类似i++是线程不安全的)。对其进行任何的操作,都是用CAS指令进行的。以下是常用的方法:public final int get() //去当前值public fi原创 2017-09-27 11:25:54 · 265 阅读 · 0 评论 -
《并发编程》--10.重入锁
在jdk5的时代,重入锁可以完全替代synchronized。但从jdk6开始对synchronized做了大量的优化,使两者在性能上差距不大。以下是冲入锁的一段简单代码public class ReenterLock implements Runnable { public static ReentrantLock lock = new ReentrantLock(); public原创 2017-08-29 14:45:39 · 294 阅读 · 0 评论 -
《并发编程》--9.线程安全和synchronizd关键字
线程安全是并行开发的基础。一般来说,程序并行就是为了获得更高的执行效率,但是高效率不能牺牲正确性为代价,否则将毫无意义。故jdk提供了synchronized关键字,来实现线程之间的同步。他的工作就是对同步的代码加锁,使得这段代码有且只有一个线程执行,从而保证线程间的安全性synchronized关键字可以有很多用法,我做了一个简单的整理,如下1.指定对象加锁:进入同步代码前需原创 2017-08-29 11:19:15 · 304 阅读 · 0 评论 -
《并发编程》--2.终止线程
通常情况下,线程执行完毕后都会自动结束,不需要手动关闭。但是也有特殊的时候。一些服务器的后台程序可能是常驻系统,他们不会正常终结。所以在一些特殊的情况下,需要我们手动终止线程。查阅jdk就会发现,有stop方法可能终止线程,但仔细发现,stop是一个废弃的方法。因为:thread.stop()方法在结束线程的时候,会直接终止线程,并且也会释放这个线程的所有锁,在这些锁刚好都是维护对象一致性原创 2017-08-17 11:19:44 · 203 阅读 · 0 评论 -
《并发编程》--3.中断线程
表面意思:让线程停止执行。其实并非如此线程中断并不会是线程立即退出,而是给线程发送一个通知,告诉该线程,别的希望你退出了!至于目标线程接到通知后会如何处理,需要目标线程自己决定。注意:这里一定要区别线程终止和线程中断线程中断的3个方法 public void Thread.interrupt(); //中断线程 public boolean Thread.isinterrupt(原创 2017-08-17 11:55:13 · 205 阅读 · 0 评论 -
《并发编程》--4.线程等待(wait)和线程通知(notity)
为了支持多线程之间的操作,jdk提供了线程等待(wait)和线程通知(notity)两个非常重要的方法,这两个方法是来自object类而不是thread类中。所以任何对象都可以调用这两个方法 。 当一个对象调用了wait()方法后,当前线程就会在这个对象上等待,直至其他线程调用了notity(),这就是线程之间的通信手段 如果一个线程调用了obj.wait(),它就会计入obj原创 2017-08-17 14:29:22 · 482 阅读 · 0 评论 -
乐观锁和悲观锁
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。一个典型的倚赖数据库的悲观锁调用: select * from account where n原创 2017-07-26 15:30:00 · 165 阅读 · 0 评论 -
脏读和不可重复读的区别
脏读 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据(Dirty Data),依据脏数据所做的操作可能是不正确的。 不可重复读 不可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也原创 2017-07-26 15:34:37 · 2335 阅读 · 1 评论 -
事务的四大特性和采用事务的隐藏方式
三、事务特性事务必须具备以下四个属性,简称ACID 属性:原子性(Atomicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行场景: 银行转账,A-100 B+100 同时成功或同时失败 一致性(Consistency):一个查询的结果必须与数据库在查询开始的状态一致(读不等待写,写不等待读)。场景: 查询数据,9:00开始查询数原创 2017-07-26 15:49:36 · 829 阅读 · 0 评论 -
《并发编程》--5.线程等待结束(join)和线程谦让(yield)
在很多情况下,一个线程的输出可能非常依赖于另外一个或者多个线程的数据。在这种情况下,这个线程就需要等待依赖线程执行完毕,才能继续执行。jdk就给我们提供了join()这个方法。public final void join() throws InterruptedException;public final synchronized void join(long millis) throws I原创 2017-08-18 11:40:13 · 264 阅读 · 0 评论 -
《并发编程》--6.Java内存模型(JMM)的关键字volatile
Java的内存模型(JMM)都是围绕着原子性,有序性,可见性。一些特殊的场合下,需要用volatile等关键字保证这些特性。当用volatile声明一个变量时,就相当于告诉虚拟机,这个变量极有可能在多个线程中修改。为了确保这个变量被修改后,程序的所有线程都能够意识到这个改动,虚拟机就必须采用一些特殊的手段,保证这个变量的可见性。声明的代码如下:static volatile i原创 2017-08-18 14:26:15 · 227 阅读 · 0 评论 -
《并发编程》--7.声明线程组
如果在一个系统中,线程数量特别多,而且功能分配比较明确,那就可以将相同功能的线程放在一个线程组里。线程组里的线程同时启动,同时停止。线程组的使用很简单,如下一个简单的demopublic class threadGroup implements Runnable{ public static void main(String[] args) { ThreadGroup tg = ne原创 2017-08-18 15:30:01 · 240 阅读 · 0 评论 -
《并发编程》--8.线程优先级
Java中的线程具有自己的优先级。优先级高的线程在竞争资源的时候更容易抢到资源。当然这只是概率的问题,如果人品不好,也会出现抢不过低优先级的情况。由于线程的优先级调度和底层的操作系统有着密切的联系,并且也不容易预测,无法精确的控制。比如一个低优先级的线程可能一直抢不到资源,而使用无法运行,就可能产生饥饿(虽然优先级低,但也不能饿死他啊),因为在严格的情况下,需要自己的代码层解决线程调度的问题。原创 2017-08-18 16:11:33 · 244 阅读 · 0 评论 -
《并发编程》--22.死锁产生的条件和动静态避免死锁
产生死锁的必要条件:1. 互斥条件:就是一个资源同时只能有一个进程占有,不能有两个或是两个以上的占有。2. 不可抢占条件:在一个进程所获取的资源在未使用完毕之前,资源申请者不能强行的从资源占有者手中抢夺资源。3. 占有申请条件:进程已经占有了一个资源,但是有申请新的资源;但是新申请的资源已经被别的进程占有了,此时该进程就会阻塞,但是在获取申请的资源之前他还会一直占有已占有的那个资源。4...原创 2017-09-27 15:29:04 · 1017 阅读 · 0 评论