虽然做java已经两年多了,但说真的对java中所谓的线程同步异步这类的东东还真不是非常的了解,由于最近在研究android上的游戏开发,看到一个游戏demo里到处都充斥着 synchronized这个关键字,而且由于在游戏开发中对线程的使用十分多,所以便写下了这些东东(高手直接忽略就可以了)。
若有幸被高手看到了这篇博文,如果有错误的话请指出,不胜感激。
关于synchronized关键字我自己写了个测试程序运行了一下,具体情况如下:
先把测试代码贴上来看看:
测试代码1:
class TxtThread implements Runnable {
int num = 4;
String str = new String();
@Override
public void run() {
// TODO Auto-generated method stub
int i = 0;
while(i < 5){
synchronized (str) {
if(num > 0){
try {
System.out.println(Thread.currentThread().getName() + " : " + i);
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.getMessage();
}
i++;
}
}
}
}
}
测试代码2:
public class Sync {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TxtThread tt = new TxtThread();
Thread t1 = new Thread(tt,"A");
Thread t2 = new Thread(tt,"B");
Thread t3 = new Thread(tt,"C");
Thread t4 = new Thread(tt,"D");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行Sync的结果如下:
运行结果1
第一次运行
B : 0
B : 1
B : 2
B : 3
C : 0
C : 1
A : 0
D : 0
A : 1
A : 2
A : 3
C : 2
C : 3
C : 4
B : 4
A : 4
D : 1
D : 2
D : 3
D : 4
-----------
第二次运行
A : 0
A : 1
D : 0
D : 1
D : 2
D : 3
D : 4
B : 0
B : 1
C : 0
C : 1
B : 2
B : 3
B : 4
A : 2
A : 3
A : 4
C : 2
C : 3
C : 4
-----------
从上面的运行结果来看,线程A、B、C、D都是逐个运行的,只不过这四个线程在运行过程中出现了对系统资源的竞争(我是这么理解的),所以导致了上面的情况发生(比如线程A运行了两步然后线程D又运行了三步,我认为这种情况是线程之间对系统资源的竞争引起的),但有一个地方是可以看出来的,线程A、B、C、D并没有同时开始运行,莫非这就是所谓的互斥?
将TxtThread类的run方法中的代码去掉synchronized包裹层去掉,运行结果如下
运行结果2
第一次运行
B : 0
D : 0
A : 0
C : 0
B : 1
D : 1
C : 1
A : 1
B : 2
D : 2
C : 2
A : 2
D : 3
B : 3
A : 3
C : 3
D : 4
B : 4
A : 4
C : 4
-----------
第二次运行
A : 0
C : 0
B : 0
D : 0
A : 1
C : 1
B : 1
D : 1
A : 2
B : 2
C : 2
D : 2
A : 3
C : 3
B : 3
D : 3
C : 4
B : 4
A : 4
D : 4
从上面的运行结果来看,线程A、B、C、D是同时开始运行的,莫非这就是所谓的同步访问?
下面的内容引用自http://java.chinaitlab.com/base/818583.html
在java编程思想中对synchronized的一点解释:
1、synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。
2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;
3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
从上面引用的内容来看,当测试程序中的TxtThread中的synchronized没有被删除的时候,相当于4个线程(A、B、C、D)同时访问了一个对象的同步方法,那么当线程A、B、C、D全部执行start方法时,它们应该是首先对系统资源进行竞争获得运行时间然后占用TxtThread的run方法中的同步语句块部分,直到某个线程运行完成之后才能允许下一个线程,这样理解的话感觉跟上面的运行结果1不结果不一样,我看了一下资料,我们在TxtThread的run方法中只是对部分关键代码进行了同步,也就是说不同的线程还是可以同时访问TxtThread方法中的run方法的,如果我们将TxtTHread的run方法中的内容写入到另外一个方法runtest()方法中,并将runtest()方法使用synchronized函数进行修饰并将其放到TxtThread的run方法中调用,那么我们就会看到下面的运行效果了,
A : 0
A : 1
A : 2
A : 3
A : 4
D : 0
D : 1
D : 2
D : 3
D : 4
C : 0
C : 1
C : 2
C : 3
C : 4
B : 0
B : 1
B : 2
B : 3
B : 4
这样就符合引用内容中的第一条所说的情况了