线程并发学习
线程并发学习—-核心概念(转载)
线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify、join)
线程并发学习—-线程阻塞(synchronized)
线程并发学习—-线程阻塞(lock)
线程并发学习—-Thread、Runnable、Callable
线程并发学习—-队列(Queue)
spring学习—-线程池
java中一些锁概念整理(转载)
简介
在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体)。
通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。
Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。
线程安全是并发编程中的重要关注点,应该注意到的是,造成线程安全问题的主要诱因有两点,
一是存在共享数据(也称临界资源),
二是存在多条线程共同操作共享数据。
在 Java 中synchronized 和 lock可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块
关键字 synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代Volatile功能),这点确实也是很重要的。
synchronized三种使用方式
- 修饰实例方法
- 修饰静态方法
- 修饰同步代码块
修饰实例方法
实例代码
public class NormalFunctionSyncDemo {
public static void main(String[] args) {
NormalFunctionSyncDemo normalFunctionSyncDemo = new NormalFunctionSyncDemo();
new Thread(new Runnable() {
@Override
public void run() {
normalFunctionSyncDemo.getA();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
NormalFunctionSyncDemo normalFunctionSyncDemo2 = new NormalFunctionSyncDemo();
normalFunctionSyncDemo2.getB();
}
}).start();
}
public synchronized void getA(){
System.out.println("get A.....");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end A");
}
public synchronized void getB(){
System.out.println("get B.....");
System.out.println("end B");
}
}
结果分析
使用同一个实例对象,会阻塞
get A…..
end A
get B…..
end B
使用不同实例对象,不会阻塞
get A…..
get B…..
end B
end A
修饰静态方法
代码示例
public class StaticFunctionSyncDemo {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
StaticFunctionSyncDemo.getA();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
StaticFunctionSyncDemo staticFunctionSyncDemo = new StaticFunctionSyncDemo();
staticFunctionSyncDemo.getB();
StaticFunctionSyncDemo.getA();
}
}).start();
}
public static synchronized void getA(){
System.out.println("get A.....");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end A");
}
public synchronized void getB(){
System.out.println("get B.....");
System.out.println("end B");
}
}
结果分析
通类直接调用或创建新的示例调用getA方法都会阻塞,getB方法不会
get A…..
get B…..
end B
end A
get A…..
end A
修饰同步代码块
代码示例
public class StaticBlockSyncDemo {
public static void main(String[] args) {
StaticBlockSyncDemo staticBlockSyncDemo = new StaticBlockSyncDemo();
new Thread(new Runnable() {
@Override
public void run() {
staticBlockSyncDemo.getA();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
StaticBlockSyncDemo staticBlockSyncDemo2 = new StaticBlockSyncDemo();
staticBlockSyncDemo.getB();
}
}).start();
}
public void getA(){
System.out.println("get A.....");
try {
synchronized (this) {
System.out.println("Method A execute");
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end A");
}
public void getB(){
System.out.println("get B.....");
try {
synchronized (this) {
System.out.println("Method B execute");
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end B");
}
}
结果分析
结果与实例方法类似,通过monitor监视器锁实现
monitor监视器锁
public void getA();
Code:
0: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #12 // String get A.....
5: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: aload_0
9: dup
10: astore_1
//通过javap命令可以看到获取monitor锁
11: monitorenter
12: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
15: ldc #14 // String Method A execute
17: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: ldc2_w #15 // long 3000l
23: invokestatic #17 // Method java/lang/Thread.sleep:(J)V
26: aload_1
27: monitorexit
参考资料
http://blog.csdn.net/javazejian/article/details/72828483?locationNum=5&fps=1
http://www.cnblogs.com/paddix/p/5374810.html