在线程程序开发过程中,当要考虑到并发问题时,常常需要用到同步技术,比如在开发银行转账系统或者是汽车售票系统这种对于数据的实时性和原子性有所要求的场合的时候,同步技术必不可少。
这里以同时开两个线程各自逐个打印不同的名字为例,运行程序时,若不使用同步时,可能会出现乱序的情况,使用同步则可以保证正确的打印顺序。
示例代码如下:
public class TraditionalThreadSynchronized {
/**
* @param args
*/
public static void main(String[] args) {
final Output output = new Output();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.output1("李逍遥");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.output1("张三丰");
}
}
}).start();
}
}
/**
* ①②两方法等价
* ③④两方法等价
* @author Administrator
*
*/
class Output{
// 没有使用同步
public void output0(String str){
int len = str.length();
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
}
// ①
public void output1(String str){
int len = str.length();
synchronized (this) {
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
}
// ②
public synchronized void output2(String str){
int len = str.length();
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
// ③
public static synchronized void output3(String str){
int len = str.length();
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
// ④
public void output4(String str){
int len = str.length();
synchronized (Output.class) {
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
}
}
①②
③④各方法单独使用都可以实现同步,区别如下:
代码中的Output类的①②两方法是等价的,都是以Output自身作为同步锁
代码中的Output类的③④两方法是等价的,都是以Output的字节码作为同步锁,由于④方法是静态的,在被调用时候Output并没有被实例化,但其字节码对象已被创建,故它和③方法用的是同样的锁。