第一个例子是同一实例方法加锁和不加锁在多线程情况下的访问情况,代码如下:
package test.caipiao.log; /** * 一个类的同一个实例,方法加锁和不加锁情况下的访问情况. * @author lfl * */ public class Test { public static void main(String[] args) { final TT tt = new TT(); Thread t1 = new Thread() { public void run() { tt.test(); //调用加锁的test() } }; Thread t2 = new Thread() { public void run() { tt.test2(); //调用加锁的test2() } }; Thread t3 = new Thread() { public void run() { tt.test3(); //调用不加锁的test3() } }; /** * t1 t2 t3 三个线程依次启动运行. */ t1.start(); t2.start(); t3.start(); System.out.println("over"); } } class TT { public synchronized void test() { for (int i = 0; i < 10000000; i++) { if (i % 10000 == 0) { System.out.println(i + " --- "); } } } public synchronized void test2() { System.out.println("test2"); } public void test3() { System.out.println("test3"); } }
输出如下(多次运行和不同计算机上运行输出结果可能不一样):
over
0 ---
test3
10000 ---
20000 ---
30000 ---
40000 ---
50000 ---
60000 ---
......
9910000 ---
9920000 ---
9930000 ---
9940000 ---
9950000 ---
9960000 ---
9970000 ---
9980000 ---
9990000 ---
test2
说明:
主线程先输出 over,主线程没有持有tt上的锁,这里就不关心了。
t1线程输出0,此时还在持有tt上的锁,t3线程就输出test3,说明线程t1持有tt上的锁,而不影响t3线程调用test3()方法,即允许其它线程方法访问该实例的非加锁方法。而最后输出test2,是在线程t1释放了tt上的锁后
线程t3获得tt上的锁才能调用test2()方法,即一个线程持有当前实例的锁,其它线程不能访问该实例的加锁方法。
-------------------------------分割线-------------------------------------------------
第二个例子是静态方法加锁和不加锁在多线程情况下的访问情况,代码如下:
package test.caipiao.log; /** * 一个类的同一个实例,方法加锁和不加锁情况下的访问情况. * @author lfl * */ public class TestStatic { public static void main(String[] args) { final TTStatic tt = new TTStatic(); Thread t1 = new Thread() { public void run() { TTStatic.test(); //调用加锁的test() } }; Thread t2 = new Thread() { public void run() { TTStatic.test2(); //或者 tt.test2(); //调用加锁的test2() } }; Thread t3 = new Thread() { public void run() { TTStatic.test3(); //调用不加锁的test3() } }; /** * t1 t2 t3 三个线程依次启动运行. */ t1.start(); t2.start(); t3.start(); System.out.println("over"); } } class TTStatic { public static synchronized void test() { for (int i = 0; i < 10000000; i++) { if (i % 10000 == 0) { System.out.println(i + " --- "); } } } public static synchronized void test2() { System.out.println("test2"); } public static void test3() { System.out.println("test3"); } }
输出如下(多次运行和不同计算机上运行输出结果可能不一样):
0 ---
10000 ---
20000 ---
30000 ---
40000 ---
50000 ---
60000 ---
70000 ---
80000 ---
90000 ---
test3
over
100000 ---
110000 ---
120000 ---
130000 ---
......
9920000 ---
9930000 ---
9940000 ---
9950000 ---
9960000 ---
9970000 ---
9980000 ---
9990000 ---
test2
test2
说明:
基本同第一个例子的分析一样,只不过这里线程持有的是TTStatic class对象上的锁,而TTStatic class对象只有一个。需要说明的是最后输出的两个test2,这个说明调用静态的加锁方法,不论是用类名调用还是实例调用,都需要获得该类的class对象上的锁。
-------------------------------------------分割线------------------------------------------------------
第三个例子是同一实例方法加锁和不加锁在多线程情况下和静态方法加锁和不加锁在多线程情况下的访问情况,代码如下:
package test.caipiao.log; /** * 一个类的同一个实例,方法加锁和不加锁情况下的访问情况. * @author lfl * */ public class TestHybrid { public static void main(String[] args) { Thread t1 = new Thread() { public void run() { TTHybrid.test(); //调用加锁的test() } }; Thread t2 = new Thread() { public void run() { TTHybrid.test2(); //调用加锁的test2() } }; Thread t3 = new Thread() { public void run() { TTHybrid.test3(); //调用不加锁的test3() } }; //下面是非静态方法调用 final TTHybrid tt = new TTHybrid(); Thread t4 = new Thread() { public void run() { tt.test4(); //调用加锁的test4() } }; Thread t5 = new Thread() { public void run() { tt.test5(); //调用加锁的test5() } }; Thread t6 = new Thread() { public void run() { tt.test6(); //调用不加锁的test6() } }; /** * t1 t2 t3 三个线程依次启动运行. */ t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); System.out.println("over"); } } class TTHybrid { public static synchronized void test() { for (int i = 0; i < 10000000; i++) { if (i % 10000 == 0) { System.out.println(i + " --- static"); } } } public static synchronized void test2() { System.out.println("test2"); } public static void test3() { System.out.println("test3"); } public synchronized void test4() { for (int i = 0; i < 10000000; i++) { if (i % 10000 == 0) { System.out.println(i + " --- instance"); } } } public synchronized void test5() { System.out.println("test5"); } public void test6() { System.out.println("test6"); } }
输出如下(多次运行和不同计算机上运行输出结果可能不一样):
0 --- static
over
test3
0 --- instance
10000 --- static
10000 --- instance
20000 --- instance
30000 --- instance
20000 --- static
40000 --- instance
50000 --- instance
30000 --- static
60000 --- instance
40000 --- static
50000 --- static
60000 --- static
70000 --- instance
test6
90000 --- static
100000 --- instance
100000 --- static
110000 --- static
120000 --- static
110000 --- instance
130000 --- static
120000 --- instance
140000 --- static
130000 --- instance
150000 --- static
......
9960000 --- instance
9370000 --- static
9970000 --- instance
9380000 --- static
9980000 --- instance
9390000 --- static
9990000 --- instance
9400000 --- static
9410000 --- static
test5
9420000 --- static
9430000 --- static
......
9970000 --- static
9980000 --- static
9990000 --- static
test2
说明:
主线程输出的over,t3线程输出的test3和t6线程输出的test6,可以看到无论是否是静态的,持有相应的锁对该类方法的访问没有影响。接着可以看到test()和test4()方法,基本是交替调用输出的,这说明持有TTHybrid class 对象上的锁和持有tt上的锁是没有直接关系的,即持有TTHybrid class 对象上的锁访问静态方法不会影响持有tt上的锁访问非静态方法。test4()输出完毕后释放tt上的锁 后,test5()方法开始输出。test()输出完毕后释放TTHybrid class 对象上的锁 后,test2()方法开始输出。
通过这三个小例子应该对Java中实例方法和静态方法在多线程下加锁和不加锁的访问情况有了一定的了解。关于synchronized关键字的具体含义请参看其它相关资料。
相关推荐
Lock锁是对象锁,仅在同一对象中,锁才会生效。(不做论证) (以下场景皆为单例模式下运行) lock.lock()的加锁方式,会使后续请求的线程堵塞等待。(方案A) lock.tryLock()的加锁方式,不会堵塞,会立即返回加锁...
利用JAVA编写的多线程运行实例 压缩文件,可直接运行 ...利用JAVA编写的多线程运行实例 压缩文件,可直接运行利用JAVA编写的多线程运行实例 压缩文件,可直接运行利用JAVA编写的多线程运行实例 压缩文件,可直接运行
java多线程小程序实例 java多线程小程序实例
java 多线程同步方法的实例 java 多线程同步方法的实例 java 多线程同步方法的实例
java多线程编程实例
描述java多线程的例子,可供进一步学习多线程的人参考
代码里面包含一个并发4个线程同时运行 全部开始 全部停止 单个停止还有点问题。 还有生产者消费者 里面的里面能帮助你理解多线程的运用!
Java Socket实例(服务器多线程) 自己写的代码
详细的讲解了java多线程的原理,并配有代码进行实战,适合java初学者和想对多线程有进一步了解的人。
java多线程编程实例 java多线程编程实例 (源程序)
java Email 多线程实例 邮件群发 javaemailjava Email 多线程实例 邮件群发 javaemailjava Email 多线程实例 邮件群发 javaemailjava Email 多线程实例 邮件群发 javaemail
《Java多线程编程实例》随书源码《Java多线程编程实例》随书源码《Java多线程编程实例》随书源码
用java平台利用java的多线程特点,编写进度条的现实以及当前时间的实时更新。
Java多线程同步具体实例.doc
java多线程编程实例源码,17章节,上百实例源码
java多线程实例
这是Java多线程编程实例一书的全部随书源码,这本书是很早的JAVA多线程编程指导书,虽然很老但是很经典,直到现在还很热,很有参考价值。
C# 多线程实例C# 多线程实例C# 多线程实例C# 多线程实例C# 多线程实例C# 多线程实例
6个非常经典的java多线程实例!欢迎下载!!!