1, Process&Threads

Most implementations of the Java virtual machine run as a single process.

Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication.

From the application programmer's point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads, as we'll demonstrate in the next section.

2, Interrupt

Interruption in Java is not pre-emptive. Put another way both threads have to cooperate in order to process the interrupt properly. If the target thread does not poll the interrupted status the interrupt is effectively ignored.

Polling occurs via the Thread.interrupted() method which returns the current thread's interrupted status AND clears that interrupt flag. Usually the thread might then do something such as throw InterruptedException.

Some API methods have built in interrupt handling. Of the top of my head this includes.

  • Object.wait()/Thread.sleep()
  • Most java.util.concurrent structures
  • Java NIO (but not java.io) and it does NOT use InterruptedException, instead using ClosedByInterruptException.

Interrupts are not explicitly handled by synchronization - synchronous blocks only gaurantee that, while executing, the block cannot be reentered by another thread.

总结: 对于像sleep()这样的方法,会自己throw InterrupttedException,如果你有程序会扔出这个interrupt,那编程的时候就catch它进行处理。否则,直接将当前方法throws InterruptedException即可。

或者自己调用Thread.interrupted()方法检测Interrupted status并进行处理。

对于一般的synchronized method,不会自动处理Interrupt并退出。

3,Java memory model

总结:在单线程的情况下,compiler也会对指令重排序来优化运行时间,只要保证说原order和重排序order执行后的结果一致即可。

但是,在多线程的情况下,compiler对线程1的指令重排序会影响线程2的执行结果。所以对于共享内存的多个线程来说,为了达到happens-before效果[即线程1的结果对线程2是可见的],Java memory model定义了多个rules。而这些rules的背后是,java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。

由于: On modern platforms, code is frequently not executed in the order it was written. It is reordered by the compiler, the processor and the memory subsystem to achieve maximum performance. On multiprocessor architectures, individual processors may have their own local caches that are out of sync with main memory. It is generally undesirable to require threads to remain perfectly in sync with one another because this would be too costly from a performance point of view. This means that at any given time, different threads may see different values for the same shared data.

Thread 1 Thread 2
x = 1; int r1 = y;
y = 2; int r2 = x;

If no reorderings are performed, and the read of y in Thread 2 returns the value 2, then the subsequent read of x should return the value 1, because the write to x was performed before the write to y. However, if the two writes are reordered, then the read of y can return the value 2, and the read of x can return the value 0.

因此: The Java Memory Model (JMM) defines the allowable behavior of multithreaded programs, and therefore describes when such reorderings are possible. It places execution-time constraints on the relationship between threads and main memory in order to achieve consistent and reliable Java applications.

Rules that Java Memory Model uses to guarantee happens-before:

1、程序次序规则:在一个单独的线程中,按照程序代码的执行流顺序,(时间上)先执行的操作happen—before(时间上)后执行的操作。

2、管理锁定规则:一个unlock操作happen—before后面(时间上的先后顺序,下同)对同一个锁的lock操作。

3、volatile变量规则:对一个volatile变量的写操作happen—before后面对该变量的读操作。

...

The basic rules imply that individual actions can be reordered, as long as the as-if-serial semantics of the thread are not violated, and actions that imply communication between threads, such as the acquisition or release of a lock, ensure that actions that happen prior to them are seen by other threads that see their effects. For example, everything that happens before the release of a lock will be seen to be ordered before and visible to everything that happens after a subsequent acquisition of that same lock.

In Java specifically, a happens-before relationship is a guarantee that memory written to by statement A is visible to statement B, that is, that statement A completes its write before statement B starts its read.

A memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction which causes a central processing unit (CPU) orcompiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction. This typically means that operations issued prior to the barrier are guaranteed to be performed before operations issued after the barrier.

4, Synchronized v.s. Volatile

对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。

加锁机制(即同步机制)既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性,原因是声明为volatile的简单变量如果当前值与该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:“count++”、“count = count+1”。

How to synchronize a HashMap?

Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn't be in synchronized block
...
synchronized (m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}

5, Atomic operations

In concurrent programming, an operation (or set of operations) is atomic, linearizable, indivisible or uninterruptible if it appears to the rest of the system to occur instantaneously.

6, Intrinsic locks

是Synchronization的基础,Synchronized method是获取当前object的instrinsic lock,而Synchronized block是获取某个object的instrinsic lock。

Synchronization is built around an internal entity known as the intrinsic lock. Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.Every object has an intrinsic lock associated with it. 

public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
什么时候prefer synchronized block?
在这个方法你只想synchronize一部分code。或者像上面这个例子,c1和c2从来不会一起使用,所以没有必要在执行inc2的时候block inc1(),提高了速度。

7, Blocking queue

http://tutorials.jenkov.com/java-concurrency/blocking-queues.html

8, "double-checked locking" pattern

9, ThreadLocal

ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
 
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
 
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。
10, Volatile more

When a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.
When thread A writes to a volatile variable and subsequently thread B reads
that same variable, the values of all variables that were visible to A prior to
writing to the volatile variable become visible to B after reading the volatile
variable. So from a memory visibility perspective, writing a volatile variable
is like exiting a synchronized block and reading a volatile variable is like
entering a synchronized block.
You can use volatile variables only when all the following criteria are met:

  • Writes to the variable
    do not depend on its current value, or you can ensure that only a single thread
    ever updates the value;
  • The variable does not
    participate in invariants with other state variables;

Locking is not required for
any other reason while the variable is being accessed.

11, Mutex vs Semaphore

A mutex provides mutual exclusion, either producer or consumer can have the key (mutex) and proceed with their work. As long as the buffer is filled by producer, the consumer needs to wait, and vice versa.

At any point of time, only one thread can work with the entire buffer. The concept can be generalized using semaphore.

A semaphore is a generalized mutex. Semaphore can be counted, while mutex can only count to 1.

12, java.util.concurrent.locks package

使用Lock是比synchronized更高级的选择,可以添加更多的逻辑。

Interface Lock[methods: lock(), unlock()], Implematations: ReentrantLock, ReadWriteLock

V.S. Synchronized: more extensive locking operations, allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects. ReadWriteLock may allow concurrent access to a shared resource.

ReentrantLock is different thing with Reentrant Synchronization[Synchronized本身就是默认reentrant的].

package com.journaldev.threads.lock; 
public class SynchronizedLockExample implements Runnable{
    private Resource resource;   
    public SynchronizedLockExample(Resource r){
        this.resource = r;
    }     
    @Override
    public void run() {
        synchronized (resource) {
            resource.doSomething();
        }
        resource.doLogging(); }}
 
package com.journaldev.threads.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConcurrencyLockExample implements Runnable{
    private Resource resource;
    private Lock lock;     
    public ConcurrencyLockExample(Resource r){
        this.resource = r;
        this.lock = new ReentrantLock();
    }   
    @Override
    public void run() {
        try {
            if(lock.tryLock(10, TimeUnit.SECONDS)){ //Here, better than Synchronized, you could set timeout to not wait forever.
            resource.doSomething();
            }
        catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            //release lock
            lock.unlock();  //Here, more complicated than Synchronized, you need to use try/finally to release the lock.
        }
        resource.doLogging(); }}

13, ExecutorService

The java.util.concurrent.ExecutorService interface represents an asynchronous execution mechanism which is capable of executing tasks in the background. An ExecutorService is thus very similar to a thread pool.

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
}); executorService.shutdown(); //会通知ExecutorService关闭,它自己会等现有的tasks执行完毕就关闭。如果你不call shutdown(),会导致JVM无法关闭。

创建ExecutorService:

ExecutorService executorService1 = Executors.newSingleThreadExecutor();

ExecutorService executorService2 = Executors.newFixedThreadPool(10);

ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

ExecutorService的方法:

  • execute(Runnable)
  • submit(Runnable)      return Future, 
    future.get();  //returns null if the task has finished correctly.
  • submit(Callable)        return Future, and future.get() return callable.call().
  • future.get() = Callable Result
  • invokeAny(...)
  • invokeAll(...)

Callable: 作用类似于Runnable,不同的是会返回结果.

import java.util.concurrent.Callable;

public class MyCallable implements Callable<Long> {  //Callable是泛型
@Override
public Long call() throws Exception { //要Override T call()方法
long sum = 0;
for (long i = 0; i <= 100; i++) {
sum += i;
}
return sum;
}
}
Callable<Long> worker = new MyCallable();
Future<Long> submit = executor.submit(worker);
public interface Future<V>
Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.

The executor framework presented in the last chapter works with Runnables. Runnable do not return result.

In case you expect your threads to return a computed result you can use java.util.concurrent.Callable. TheCallable object allows to return values after completion.

												

[Java Basics] multi-threading的更多相关文章

  1. [Java Basics] Reflection

    For every type of object, the Java virtual machine instantiates an immutable instance of java.lang.C ...

  2. [Java Basics] Collection

    除了Java collection class/interface外,方便的有Google guava的utility class: Lists/Sets/Maps/Queues, 用它们可以方便地创 ...

  3. [Java Basics] Stack, Heap, Constructor, I/O, Immutable, ClassLoader

    Good about Java: friendly syntax, memory management[GC can collect unreferenced memory resources], o ...

  4. Summary of Java basics review data

    1.标识符      用于命名程序的对象,如方法名,变量名,规则是: a.大小写敏感 b.由英文字符,文字字符,美元符号,下划线和数字组成,但不能以数字开头 c.不能是关键字 2.%:求余运算符    ...

  5. java:提示Could not initialize class sun.awt.X11GraphicsEnvironment

    前几天发现tomcat提示 Could not initialize class sun.awt.X11GraphicsEnvironment  问题.以为不验证,就没太关注,今天发现,有同事提示了个 ...

  6. 【转】O'Reilly Java系列书籍建议阅读顺序(转自蔡学庸)

    Learning Java the O'Reilly's Way (Part I) Java 技术可以说是越来越重要了,不但可以用在计算机上,甚至连电视等家电用品,行动电话.个人数字助理(PDA)等电 ...

  7. 【Java】-NO.20.Exam.1.Java.1.001- 【1z0-807】- OCEA

    1.0.0 Summary Tittle:[Java]-NO.20.Exam.1.Java.1.001-[1z0-807] Style:EBook Series:Java Since:2017-10- ...

  8. 【java异常】org.springframework.web.util.NestedServletException: Handler processing failed;Can't connect to X11 window server using 'localhost:10.0' as the value of th

    tomcat工程中创建二维码失败.抛出异常Can't connect to X11 window server using 'localhost:10.0' as the value of th 因为 ...

  9. java 利用ManagementFactory获取jvm,os的一些信息--转

    原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...

随机推荐

  1. twemproxy - Proxy Server for Redis 安装测试

    1. 安装 (1) 系统环境 测试用的服务器为阿里云ECS,4核8G,CentOS6.3 64bit. 部署了3个Redis实例,监听端口号为7410,7420,7430,设置maxmemory为25 ...

  2. (转)MySQL命令行--导入导出数据库

    MySQL命令行导出数据库:   1,进入MySQL目录下的bin文件夹:cd MySQL中到bin文件夹的目录 如我输入的命令行:cd C:\Program Files\MySQL\MySQL Se ...

  3. [问题2014A12] 解答

    [问题2014A12]  解答 将问题转换成几何的语言: 设 \(\varphi,\psi\) 是 \(n\) 维线性空间 \(V\) 上的线性变换, 满足 \(\varphi\psi=\psi\va ...

  4. 类函数和对象函数 PHP

    1. bool class_exists ( string $class_name [, bool $autoload = true ] )  检查指定的类是否已定义. 如果由 class_name  ...

  5. js继承之call,apply和prototype随谈

    在js中,call,apply和prototype都可以实现对象的继承,下面我们看一个例子: function FatherObj1() { this.sayhello = "I am jo ...

  6. iOS - Mac Vim 编辑器

    Mac Vim 编辑器 1)vi 文本编辑器 1.打开一个文件:vi 文件名 按住 shift 连按两次 z 键( :q )退出 vi 编辑器 2.vi 两种模式:第一是命令模式(按 esc 进入命令 ...

  7. python yield的初识

    ---------2016-5-18 10:49:45-- source:

  8. python 学习中遇到的问题

    一.安装pip中遇到的问题. 出现错误:ImportError:DLL load failed :%1不是有效的win32应用程序 出现问题解答: 主要是由于安装的python版本和所下载的安装包版本 ...

  9. [cocos2d-x]OPENGL ES支持的像素格式

    OPENGL ES最多支持32位颜色值. 支持的像素格式有以下几种: 客户端格式 GL格式 GL数据类型 字节数 RGBA8888 GL_RGBA GL_UNSIGNED_BYTE 4 RGB888 ...

  10. Modify textures at runtime

    动态修改Texture Modify textures at runtime?http://answers.unity3d.com/questions/7906/modify-textures-at- ...