杂乱无章
- 站在程序性能的角度看,在单处理器的机器上使用并发不会有对改善性能有什么影响,除非一个任务可能阻塞。
- volatile(易变性):long和double是分开的两个32位操作,所以是非原子性的,可能会出现在操作一部分后系统出现上下文切换,造成读写数据错误。使用volatile定义long和double,保证其原子性。(64位系统中long和double也是非原子性的,详见java虚语言规范)
- volatile关键字确保属性在整个应用中的可见性。如果声明一个属性为volatile,则一旦对这个属性进行写入操作,所有的读取都能立即发现它的变化。即使涉及到处理器缓存时,它也是正确的-volatile修饰的属性会立即写入内存中(不放在处理机缓存中),而读取是从内存中获取。
- It’s important to understand that atomicity and volatility are distinct concepts. An atomic operation on a non-volatile field will not necessarily be flushed to main memory, and so another task that reads that field will not necessarily see the new value. If multiple tasks are accessing a field, that field should be volatile; otherwise, the field should only be accessed via synchronization. Synchronization also causes flushing to main memory, so if a field is completely guarded by synchronized methods or blocks, it is not necessary to make it volatile.(读着就觉得牛逼)
Any writes that a task makes will be visible to that task, so you don’t need to make a field volatile if it is only seen within a task.
volatile doesn’t work when the value of a field depends on its previous value (such as incrementing a counter), nor does it work on fields whose values are constrained by the values of other fields, such as the lower and upper bound of a Range class which must obey the constraint lower <= upper.
线程状态
- New:当线程创建时,线程在这个状态停留片刻时间。它开辟所需要的所有系统资源和进行初始化。在这个时刻,这个线程有资格去获取CPU时间。接下来调度器会将这个线程转换到可运行状态或阻塞状态。
- Runnable:这意味着当此线程获取到CPU分片机制所提供的CPU执行周期时,可以运行。所以此线程在任何时刻可能运行也可能不运行,但是当时间调度机制安排它运行时,没有其他地方阻挡它运行。它没有处于死亡或者阻塞状态。
- Blocked:线程可以运行,但是某些地方阻挡了其运行。当一个线程处于阻塞状态,线程调度器会直接跳过它,并且不会给它CPU时间。如果没有再次进入可运行状态,它不会进行任何其他操作。
- Dead:当一个线程处于死亡或者终结状态时,它将不会再被调度执行,也将不再会获取CPU时间。它的任务结束了,也不会再次运行了。一个任务死亡的一种方式是从run()方法中返回,但是一个任务线程也可以被中断。
造成阻塞的几种情况
- 通过调用sleep(milliseconds)方法使任务进入睡眠状态,在这种状况下,在指定的时间内,它不会运行。
- 通过wait()方法挂起了线程的执行。当这个线程收到notify()或者notifyAll()信息(or the equivalent signal( ) or signalAll( ) for the Java SE5 java.util.concurrent library tools),它将再次可以运行。
- 任务在等待I/O完成。
- 任务在尝试调用另一个对象上的synchronized方法,而由于那个对象的锁已被其他任务获取到,这个任务不能获取那个对象上的锁。
Java线程中,异常用来做终止线程
- sleep(milliseconds)造成的阻塞可通过interrupt()方法中断,I/O阻塞和synchronized造成的阻塞不可以通过interrupt()中断。
- 可以通过关闭造成任务阻塞的资源(io流等)来终止线程。
- 由ReentrantLocks造成阻塞的任务可以通过interrupt()方法中断。
杂乱无章
- Sleep()与yield()都不释放锁,wait()释放锁。
- wait( ), notify( )和notifyAll( )方法会操作锁(sleep()不操作锁)。这三个方法只能在同步方法或者同步代码块中调用(在非同步方法和同步代码块中运行时会抛出异常),而sleep()可以在非同步方法和代码块中调用。
- java.util.concurrent.BlockingQueue:同步队列,一次只允许一个任务从队列中获取元素或者向队列中插入元素。
当队列是空的,而一个任务尝试去获取队列中的元素时,这个任务将被挂起;当有元素可以访问时挂起的任务再继续执行。
相比于wait()和notifyAll(),同步队列更加简洁和可靠。
发生死锁的四个条件
- 互相排斥。至少一个资源是所有任务不共享的。
- 至少一个任务已经持有一个资源,并且等待获取正在被另一个任务所持有的资源。
- 一个资源不能提前从一个任务中拿走。多个任务只能以正常的事件方式释放资源。
- 循环等待。
杂乱无章
- DelayQueue:is an unbounded BlockingQueue of objects that implement the Delayed interface.继承了同步队列,用来放实现了Delaye接口的元素 。放置的所有元素按照延迟时间排序,延迟时间短的元素先执行。
- PriorityBlockingQueue:is basically a priority queue that has blocking retrieval operations.是一个有同步访问操作的优先级队列。队列中元素实现Comparable接口,用来比较优先级。
- Semaphore:一般的锁(concurrent.locks锁或者内置的synchronized锁)一次只允许一个任务来访问资源。一个计数信号量(semaphore)允许n个任务同时访问资源。
- Exchanger:是在两个任务中交换对象的同步屏障。当一个任务进入同步屏障时,它持有一个对象,当它离开时,它持有的是之前被另一个任务所持有的对象,而另一个任务持有它进入同步屏障时所持有的那个对象。
- CopyOnWriteArrayList:List的子类,当遍历元素的时候允许remove(),不会抛出ConcurrentModificationException异常。
免锁容器
- 实现机制
当读写和修改同时发生时,用户只能访问到修改完毕的结果。修改发生在原本数据结构的一部分中,这部分保存了这个数据结构的一个分离的副本。当修改进行中时,这个副本是不可见的。只有当修改完成时,被修改的这部分副本的数据结构原子的替换掉原来的数据结构。接下来用户看到的就是修改过后的数据结构。CopyOnWriteArrayList就是通过这个机制实现(此list在多个任务遍历修改时不会抛ConcurrentModificationException)。 - Vector and Hashtable had many synchronized methods.
- CopyOnWriteArraySet uses CopyOnWriteArrayList to achieve its lock-free behavior.
- ConcurrentHashMap and ConcurrentLinkedQueue use similar techniques to allow concurrent reads and writes, but only portions of the container are copied and modified rather than the entire container. However, readers will still not see any modifications before they are complete. ConcurrentHashMap doesn’t throw ConcurrentModificationExceptions.
- ConcurrentHashMap and ConcurrentLinkedQueue use similar techniques to allow concurrent reads and writes, but only portions of the container are copied and modified rather than the entire container. However, readers will still not see any modifications before they are complete. ConcurrentHashMap doesn’t throw ConcurrentModificationExceptions.
- 乐观锁:
- ReadWriteLocks(读写锁):当多个任务对一个数据结构读的比较频繁,但是相对来说写的比较不频繁时,可以用读写锁来进行优化。
The ReadWriteLock allows you to have many readers at one time as long as no one is attempting to write. If the write lock is held, then no readers are allowed until the write lock is released.