synchornized关键字的几种用法如下:
1、作用在方法上,锁是当前实例对象
- 不同线程对于同一个对象的锁具有互斥性
当A线程获取到锁之后,B线程只能等A线程释放锁之后才能获取
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method method1 = new sync_method();
Thread thread1 = new Thread(method1);
Thread thread2 = new Thread(method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
public synchronized void f(){
System.out.println("f() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("f() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
f();
}
}
输出:
f() start by: Thread-0
f() end by: Thread-0
f() start by: Thread-1
f() end by: Thread-1
上面这个例子中,因为两个线程是共用一把锁,因此线程2只能等线程1执行结束之后才能运行
- 不同线程对于不同对象相当于异步
synchornized获得的是对象锁,如果有多个对象,jvm就会创建多个锁
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method method1 = new sync_method();
sync_method method2 = new sync_method();
Thread thread1 = new Thread(method2);
Thread thread2 = new Thread(method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
public synchronized void f(){
System.out.println("f() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("f() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
f();
}
}
输出:
f() start by: Thread-0
f() start by: Thread-1
f() end by: Thread-1
f() end by: Thread-0
上面这个例子中,因为两个线程填入的实例不一样,表示两个线程的锁是不一样的,因此说明线程2不需要等线程1执行完毕,就可以执行该实例中的同名方法
- 所有对象都自动含有单一的锁
当对象在调用其任意synchornized方法时,此对象都会被加锁,这时该对象上的其他synchornized方法只有等到前一个方法调用完毕并释放锁之后才能被调用。
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method method1 = new sync_method();
Thread thread1 = new Thread(method1);
Thread thread2 = new Thread(method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
private static int count=1;
public synchronized void f(){
System.out.println("f() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("f() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void g(){
System.out.println("g() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("g() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
if (count==1){
count=2;
f();
}else{
count=1;
g();
}
}
}
输出:
f() start by: Thread-0
f() end by: Thread-0
g() start by: Thread-1
g() end by: Thread-1
- 一个任务可以多次获得对象的锁
如果一个方法在同一个对象上调用第二个方法,后者又调用了同一个对象上的另一个方法,就会发生这种情况。jvm负责跟踪对象加锁的次数。如果一个对象被解锁(即完全释放锁),计数器就会变为0;在任务第一次给对象加锁时,计数器变为1.每当这个相同的任务在这个对象上获取锁时,计数器都会递增。显然只有首先获得锁的任务才能被允许继续加锁。每当任务离开一个synchornized方法,计数器递减,当计数器为0时,释放锁,此时,别的任务就可以获得此资源。
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method method1 = new sync_method();
Thread thread1 = new Thread(method1);
Thread thread2 = new Thread(method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
private static int count=1;
public synchronized void f(){
System.out.println("f() start by: "+Thread.currentThread().getName());
try {
g();
Thread.sleep(1000);
System.out.println("f() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void g(){
System.out.println("g() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("g() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
if (count==1){
count=2;
f();
}else{
count=1;
g();
}
}
}
输出:
f() start by: Thread-0
g() start by: Thread-0
g() end by: Thread-0
f() end by: Thread-0
g() start by: Thread-1
g() end by: Thread-1
- 同步不能继承
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method method1 = new sync_method();
sync_method method2 = new sync_method();
sync_method1 sync_method1 = new sync_method1();
Thread thread1 = new Thread(sync_method1);
Thread thread2 = new Thread(sync_method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
private static int count=1;
public synchronized void f(){
System.out.println("f() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("f() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void g(){
System.out.println("g() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("g() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
if (count==1){
count=2;
f();
}else{
count=1;
g();
}
}
}
class sync_method1 extends sync_method{
public void f(){
System.out.println("s() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("s() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
super.f();
}
@Override
public void run() {
f();
}
}
输出:
s() start by: Thread-0
s() start by: Thread-1
s() end by: Thread-0
s() end by: Thread-1
f() start by: Thread-0
f() end by: Thread-0
f() start by: Thread-1
f() end by: Thread-1
不难发现,两个线程进入子类几乎是一起进入的。
- 父类和子类是同一个锁
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method1 sync_method1 = new sync_method1();
Thread thread1 = new Thread(sync_method1);
Thread thread2 = new Thread(sync_method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
private static int count=1;
public synchronized void f(){
System.out.println("f() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("f() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void g(){
System.out.println("g() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("g() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
if (count==1){
count=2;
f();
}else{
count=1;
g();
}
}
}
class sync_method1 extends sync_method{
public synchronized void f(){
System.out.println("s() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("s() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
super.f();
}
@Override
public void run() {
f();
}
}
输出:
s() start by: Thread-0
s() end by: Thread-0
f() start by: Thread-0
f() end by: Thread-0
s() start by: Thread-1
s() end by: Thread-1
f() start by: Thread-1
f() end by: Thread-1
可以发现,只有当一个线程释放锁之后。另一个线程才能获得资源
2、作用在方法块上,锁就是括号里的对象
- 不同线程对于不同对象,相当于异步
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method method1 = new sync_method();
sync_method method = new sync_method();
Thread thread1 = new Thread(method);
Thread thread2 = new Thread(method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
private static int count=1;
private sync_method1 method1=new sync_method1();
@Override
public void run() {
method1.f();
}
}
class sync_method1{
public void f(){
synchronized (this){
System.out.println("s() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("s() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出:
s() start by: Thread-0
s() start by: Thread-1
s() end by: Thread-0
s() end by: Thread-1
- 当锁是类对象时
package com.piao.thread1;
public class test_sync_method {
public static void main(String[] args) {
sync_method method1 = new sync_method();
sync_method method = new sync_method();
Thread thread1 = new Thread(method);
Thread thread2 = new Thread(method1);
thread1.start();
thread2.start();
}
}
class sync_method implements Runnable{
private static int count=1;
private sync_method1 method1=new sync_method1();
@Override
public void run() {
method1.f();
}
}
class sync_method1{
public void f(){
synchronized (sync_method1.class){
System.out.println("s() start by: "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
System.out.println("s() end by: "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
s() start by: Thread-0
s() end by: Thread-0
s() start by: Thread-1
s() end by: Thread-1