Synchronized作用:Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
1.Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”。
2.Synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”。
注意:一个是对象锁 一个是Class类锁
以下为亲测
测试同步方法的代码:参数是后面为了测试 不同对象调用同一方法而加的,可以一开始加进去,不想修改就在这里说明一下
sleep();只会暂停当前线程不会释放锁
public class SynchronizedTest {
public static SynchronizedTest staticIn = new SynchronizedTest(); //静态对象
public synchronized void method1(String threadName){ //非静态方法1
for(int i = 0;i < 10;i++){
System.out.println("method1 is running!" + threadName);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized void method2(String threadName){ //非静态方法2
for( int i = 0; i < 10 ; i++){
System.out.println("method2 is running!" + threadName);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized static void staticMethod1(String threadName){ //静态方法1
for( int i = 0; i < 10 ; i++){
System.out.println("static method1 is running!" + threadName);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized static void staticMethod2(String threadName){ //静态方法2
for( int i = 0; i < 10 ; i++){
System.out.println("static method2 is running!" + threadName);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
同一对象
情形一:同一个对象在两个线程中分别访问该对象的两个同时是静态或者两个同时是非晶态的同步方法
结果:会产生互斥。
解释:因为锁针对的是对象,当对象调用一个synchronized方法时,其他同步方法需要等待其执行结束并释放锁后才能执行。
1.非静态同步方法(静态的也是一样的结果)
public static void main(String[] args) throws InterruptedException {
SynchronizedTest test = SynchronizedTest.staticIn;
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
test.method1();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
test.method2();
}
});
ScheduledExecutorService service = Executors.newScheduledThreadPool(1000);
service.execute(t1);
service.execute(t2);
service.shutdown();
}
结果:现成t1先完成,没有出现抢占CPU的情况
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
情形二:同一个对象在两个线程中分别访问该对象的一个静态同步方法和非静态同步方法
结果:并不会产生互斥。
解释:锁针对的是对象,因为静态方法的锁对象是当实例对象的Class类对象,而非静态方法的锁对象是当前实例对象
public static void main(String[] args) throws InterruptedException {
SynchronizedTest test = SynchronizedTest.staticIn;
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
test.method1();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
test.staticMethod2();
}
});
ScheduledExecutorService service = Executors.newScheduledThreadPool(1000);
service.execute(t1);
service.execute(t2);
service.shutdown();
}
结果:两个线程是互不影响的,出现抢占CPU的乱序现象
method1 is running!
static method2 is running!
method1 is running!
static method2 is running!
method1 is running!
static method2 is running!
method1 is running!
static method2 is running!
method1 is running!
static method2 is running!
static method2 is running!
method1 is running!
static method2 is running!
method1 is running!
static method2 is running!
method1 is running!
static method2 is running!
method1 is running!
static method2 is running!
method1 is running!
不同对象
情形三:不同对象在两个线程中调用同一个非静态同步方法
结果:不会产生互斥。
解释:因为是两个对象,锁针对的是对象,并不是方法,所以可以并发执行,不会互斥。形象的来说就是因为我们每个线程在调用方法的时候都是new 一个对象,那么就会出现两个空间,两把钥匙,
测试代码:参数是为了这里测试区别加的
这里注意:通过静态构造得到的是同一个对象
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
new SynchronizedTest().method1("t1");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
SynchronizedTest.staticIn.method1("t2");
}
});
ScheduledExecutorService service = Executors.newScheduledThreadPool(1000);
service.execute(t1);
service.execute(t2);
service.shutdown();
}
结果:不互斥的
method1 is running!t1
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t1
method1 is running!t2
method1 is running!t1
情形四:不同对象在两个线程中调用同一个静态同步方法
结果:会产生互斥。
解释:因为是锁对象都是Class类,是同一个对象
测试代码:参数是为了这里测试区别加的
这里注意:通过静态构造得到的是同一个对象
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
new SynchronizedTest().staticMethod1("t1");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
SynchronizedTest.staticIn.staticMethod1("t2");
}
});
ScheduledExecutorService service = Executors.newScheduledThreadPool(1000);
service.execute(t1);
service.execute(t2);
service.shutdown();
}
结果:互斥
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t1
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2
static method1 is running!t2