本文总结自:Java线程同步:synchronized锁住的是代码还是对象
结论:
1.synchronized修饰的非static方法其实是在执行方法前,先获取this对象的锁,如果对象锁被其他线程获取了,则进入阻塞状态;
2.synchronized(mutex)修饰的代码段是先获取mutex对象的锁,然后再进入代码段,否则进入阻塞;
3.对于synchronized修饰static方法,如1.差不多,只不过现在是获取该类的class对象,由于一个类只有一个class对象,这时可以真正做到只有一个线程能够执行该代码段;
4.设计同步时,尽量避免直接使用synchronized修饰的非static方法,尽量缩小核心的同步代码段,最大化利用CPU;
5.实例化多个含有synchronized代码段的对象时,可能由于设置的对象锁是非全局的,依然可以有多个线程同时执行同一个代码段。
代码
实例化多个对象,在多个线程里执行synchronized修饰的非static方法。
package cc.appweb.www;
public class SynchTest {
public static void main(String[] args){
Sy[] sys = new Sy[5];
WorkThread[] workThread = new WorkThread[5];
for(int i = 0 ; i < 5 ; i++){
sys[i] = new Sy();
workThread[i] = new WorkThread();
workThread[i].setPara(sys[i], i);
workThread[i].start();
}
try{
Thread.sleep(2000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Main Thread end!");
}
}
class Sy{
public synchronized void run(int flag){
System.out.println("Instance "+flag + " run!" );
try{
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Instance " + flag + " end!" );
}
}
class WorkThread extends Thread{
private Sy worker;
private int flag;
public void setPara(Sy sy, int flag){
worker = sy;
this.flag = flag;
}
@Override
public void run(){
worker.run(flag);
}
}
输出
Instance 0 run!
Instance 1 run!
Instance 3 run!
Instance 4 run!
Instance 2 run!
Instance 0 end!
Instance 1 end!
Instance 2 end!
Instance 4 end!
Instance 3 end!
Main Thread end!
这时多个线程可以同时执行同一个代码段,因为获取的对象锁都不同
将多个Sy实例修改为一个Sy实例
package cc.appweb.www;
public class SynchTest {
public static void main(String[] args){
//Sy[] sys = new Sy[5];
Sy sy = new Sy();
WorkThread[] workThread = new WorkThread[5];
for(int i = 0 ; i < 5 ; i++){
//sys[i] = new Sy();
workThread[i] = new WorkThread();
workThread[i].setPara(sy, 1);
workThread[i].start();
}
try{
//Thread.sleep(2000);
Thread.sleep(20000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Main Thread end!");
}
}
class Sy{
public synchronized void run(int flag){
System.out.println("Instance "+flag + " run!" );
try{
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Instance " + flag + " end!" );
}
}
class WorkThread extends Thread{
private Sy worker;
private int flag;
public void setPara(Sy sy, int flag){
worker = sy;
this.flag = flag;
}
@Override
public void run(){
worker.run(flag);
}
}
输出
Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Main Thread end!
可见run 和 end变成了成对出现,也就是说其他线程执行run方法时被阻塞了。
生成多个实例,在方法里获取本身对象
package cc.appweb.www;
public class SynchTest {
public static void main(String[] args){
Sy[] sys = new Sy[5];
//Sy sy = new Sy();
WorkThread[] workThread = new WorkThread[5];
for(int i = 0 ; i < 5 ; i++){
sys[i] = new Sy();
workThread[i] = new WorkThread();
workThread[i].setPara(sys[i], i);
workThread[i].start();
}
try{
Thread.sleep(2000);
//Thread.sleep(20000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Main Thread end!");
}
}
class Sy{
public void run(int flag){
synchronized (this) {
System.out.println("Instance "+flag + " run!" );
try{
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Instance " + flag + " end!" );
}
}
}
class WorkThread extends Thread{
private Sy worker;
private int flag;
public void setPara(Sy sy, int flag){
worker = sy;
this.flag = flag;
}
@Override
public void run(){
worker.run(flag);
}
}
</pre><p></p><pre>
输出
Instance 0 run!
Instance 2 run!
Instance 1 run!
Instance 3 run!
Instance 4 run!
Instance 1 end!
Instance 0 end!
Instance 4 end!
Instance 3 end!
Instance 2 end!
Main Thread end!
依然会同时执行该代码段
生成多个实例,在方法里获取该类的class对象
class Sy{
public void run(int flag){
synchronized (Sy.class) {
System.out.println("Instance "+flag + " run!" );
try{
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Instance " + flag + " end!" );
}
}
}
输出
Instance 0 run!
Instance 0 end!
Instance 4 run!
Instance 4 end!
Instance 3 run!
Instance 3 end!
Instance 2 run!
Instance 2 end!
Instance 1 run!
Instance 1 end!
Main Thread end!
这时run和end也成对出现了。
测试synchronized static方法
package cc.appweb.www;
public class SynchTest {
public static void main(String[] args){
WorkThread[] workThreads = new WorkThread[5];
for(int i = 0; i < 5 ; i++){
workThreads[i] = new WorkThread(i);
workThreads[i].start();
}
try{
Thread.sleep(10000);
}catch (Exception e) {
e.printStackTrace();
}
}
}
class Sy{
public synchronized static void staticRun(int flag){
System.out.println("Instance " + flag + " run!");
try{
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Instance " + flag + " end!" );
}
}
class WorkThread extends Thread{
private int flag;
public WorkThread(int flag){
this.flag = flag;
}
@Override
public void run(){
Sy.staticRun(flag);
}
}
输出
Instance 0 run!
Instance 0 end!
Instance 3 run!
Instance 3 end!
Instance 4 run!
Instance 4 end!
Instance 2 run!
Instance 2 end!
Instance 1 run!
Instance 1 end!
为了说明synchronized static 方法获取的是类的class对象,可以在方法内添加wait,notify的调用。
package cc.appweb.www;
public class SynchTest {
public static void main(String[] args){
WorkThread[] workThreads = new WorkThread[5];
for(int i = 0; i < 5 ; i++){
workThreads[i] = new WorkThread(i);
workThreads[i].start();
}
try{
Thread.sleep(10000);
}catch (Exception e) {
e.printStackTrace();
}
}
}
class Sy{
private static int count=0;
public synchronized static void staticRun(int flag){
count ++;
System.out.println("Instance " + flag + " run!");
try{
if(count != 5 ) // 控制线程的等待
Sy.class.wait();
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Instance " + flag + " end!" );
Sy.class.notify();
}
}
class WorkThread extends Thread{
private int flag;
public WorkThread(int flag){
this.flag = flag;
}
@Override
public void run(){
Sy.staticRun(flag);
}
}
输出
Instance 0 run!
Instance 3 run!
Instance 2 run!
Instance 1 run!
Instance 4 run!
Instance 4 end!
Instance 0 end!
Instance 3 end!
Instance 2 end!
Instance 1 end!
run和end已经不成对出现,说明获取的就是class对象。
生成多个实例,在方法里获取本身对象