缘由:
理解java中synchronized关键字。
指标:理解synchronized的含义。明确synchronized关键字修饰普通方法、静态方法和代码快时锁对象的差异。
有如下一个类A
class A{
public synchronized void a(){
}
public synchronized void b(){
}
}
然后创建两个对象
A a1 = new A();
A a2 = new A();
然后在两个线程中并发访问如下代码:
Thread1 Thread2
a1.a() a2.a()
请问两者能否构成线程同步呢?
如果A的定义是下面这种的呢?
class A{
public staic synchronized void a(){
}
public static synchronized void b(){
}
}
答案:
第一种情况,不构成同步
第二种情况,够成线程同步
解释:
synchroinzed 关键字修饰普通的方法,针对的是方法所在的对象,锁定的这个方法中的对象只在同一个对象中被锁。synchronized 关键字修饰静态方法,因为静态方法是类方法,和对象无关,所以在不同的对象中也是线程同步的。synchronized修饰代码块,如果为synchronized(this/对象名){}和普通方法是一样的,如果为synchronized(类名.class){}和静态方法是一样的。但是代码同步的仅仅是代码块中的属性或者对象。方法同步的是整个方法体。
扩展:
针对这个问题回顾java中线程的大部分知识:
1.线程的启动方式,new Thread(Runnable对象),其中Runnable是线程驱动的任务,要依附在线程上才能实现
线程行为,否则这个接口并没有特殊之处。
代码如下:
package com.xrc.learnThread;
public class LiftOff implements Runnable{
private static int count = 1000000;
private static int text= 0;
private static int text1= 0;
private static int text2= 0;
private int threadCount = 0;
LiftOff(int i ){
threadCount = i;
}
private synchronized void increase(){
// synchronized (this){
text ++;
// }
text1 ++;
}
private void increase1(){
// synchronized (this){
text2 ++;
// }
}
public void run() {
for(int i = 0; i < count ;i++){
increase();
increase1();
}
}
public static void main(String[] args){
LiftOff liftOff = new LiftOff(1);
LiftOff liftOff1 = new LiftOff(2);
Thread t1 = new Thread(liftOff);
Thread t2 = new Thread(liftOff);
// Thread t1 = new Thread(liftOff);
// Thread t2 = new Thread(liftOff1);
t1.start();
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(text);
System.out.println(text1);
System.out.println(text2);
}
}
运行结果:
2000000
2000000
1999910
证明了作用于同一对象上的上锁的普通方法是可以实现同步的,同时说明了synchronized仅仅针对的是本方法了面的对象,对其他方法不起作用。
2、使用Executor
有ExecutorService exec = Executors.newCachedThreadPool();
ExecutorService exec = Executors.newFixedThreadPool(5);
ExecutorSercice exec = Executors.singleThreadExecutor();
代码如下:
package com.xrc.learnThread;
public class LiftOff implements Runnable{
private static int count = 10;
private static int text= 0;
private static int text1= 0;
private static int text2= 0;
private int threadCount = 0;
LiftOff(int i ){
threadCount = i;
}
private synchronized void increase(){
// synchronized (this){
text ++;
System.out.println(threadCount +" : " + text);
// }
}
private void increase1(){
// synchronized (this){
text2 ++;
// }
}
public void run() {
for(int i = 0; i < count ;i++){
increase();
increase1();
}
}
}
package com.xrc.learnThread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadTool {
public static void main(String[] args){
for(int i = 0; i<2;i++){
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new LiftOff(i));
exec.shutdown();
}
}
}
结果如下:
0 : 1
0 : 2
0 : 3
0 : 4
0 : 5
0 : 6
0 : 7
0 : 8
1 : 1
0 : 9
1 : 2
0 : 10
1 : 3
1 : 4
1 : 5
1 : 6
1 : 7
1 : 8
1 : 9
1 : 10
4 : 1
2 : 1
4 : 2
4 : 3
4 : 4
2 : 2
4 : 5
3 : 1
4 : 6
2 : 3
4 : 7
3 : 2
4 : 8
2 : 4
4 : 9
3 : 3
4 : 10
2 : 5
2 : 6
3 : 4
2 : 7
3 : 5
2 : 8
3 : 6
2 : 9
3 : 7
2 : 10
3 : 8
3 : 9
3 : 10