1.1、两个线程同时访问一个对象的同步方法
//两个线程 t1,t2 同时访问SynchronizedObjectMethod3对象中的Method()方法:
package disappear.request;
public class SynchronizedObjectMethod3 implements Runnable{
static SynchronizedObjectMethod3 instence = new SynchronizedObjectMethod3();
@Override
public void run() {
Method();
}
//争抢的是同一把锁
public synchronized void Method() {
System.out.println("My name is :"+Thread.currentThread().getName());
try{
Thread.sleep(3000);
}catch(InterruptedException ie){
ie.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" is over!");
}
public static void main(String [] args){
Thread t1 = new Thread(instence);
Thread t2 = new Thread(instence);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("Over!");
}
}
1.2、两个线程同时访问两个对象的同步(synchronized)方法
//两个线程 t1,t2 分别访问的是两个Phenomenon1对象中的Method()方法
package Synchronized.Seven.Phenomenon;
public class Phenomenon1 implements Runnable{
static Phenomenon1 instence1 = new Phenomenon1();
static Phenomenon1 instence2 = new Phenomenon1();
public synchronized void Method(){
System.out.println("My name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" is over!");
}
@Override
public void run() {
Method();
}
public static void main(String [] args){
Thread t1 = new Thread(instence1);
Thread t2 = new Thread(instence2);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("all is over!");
}
}
1.3、两个线程访问的是不同对象的同步(synchronized)静态方法
//两个线程 t1,t2 分别访问的是两个Phenomenon1对象中的Method()方法,但是Method()方法是静态方法。
package Synchronized.Seven.Phenomenon;
public class Phenomenon3 implements Runnable{
static Phenomenon3 instence1 = new Phenomenon3();
static Phenomenon3 instence2 = new Phenomenon3();
public static synchronized void Method(){
System.out.println("My name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" is over!");
}
@Override
public void run() {
Method();
}
public static void main(String [] args){
Thread t1 = new Thread(instence1);
Thread t2 = new Thread(instence2);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("all is over!");
}
}
1.4、同时访问同步方法和非同步方法
//两个线程 t1,t2 访问的是一个Phenomenon4对象中的Method1()方法和Method2()方法,但是Method1()方法由synchronized修饰。
package Synchronized.Seven.Phenomenon;
public class Phenomenon4 implements Runnable
{
static Phenomenon4 instence = new Phenomenon4();
public synchronized void Method1() {
System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
public void Method2() {
System.out.println("I'm a commend method,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
Method1();
}else{
Method2();
}
}
public static void main(String[] args){
Thread t1 = new Thread(instence);
Thread t2 = new Thread(instence);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("all is over!");
}
}
结论:synchronized 关键字只作用于修饰的一个方法,不会影响同类中的其他方法的并发操作。
1.5、访问同一个对象的不同普通同步方法
//两个线程 t1,t2 访问的是一个Phenomenon5对象中的Method1()方法和Method2()方法,两个方法都被synchronized修饰。
package Synchronized.Seven.Phenomenon;
public class Phenomenon5 implements Runnable{
static Phenomenon5 instence = new Phenomenon5();
public synchronized void Method1() {
System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
public synchronized void Method2() {
System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
Method1();
}else{
Method2();
}
}
public static void main(String [] args){
Thread t1 = new Thread(instence);
Thread t2 = new Thread(instence);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("all is over!");
}
}
结论:synchronized默认指定了this这个对象,作为他的锁。所以synchronized修饰的两个或者两个以上的方法是相互受到影响的。
1.6、同时访问静态的synchronized方法和非静态的synchronized方法
//两个线程 t1,t2 访问的是一个Phenomenon6对象中的Method1()方法和Method2()方法,两个方法都被synchronized修饰,但是Method1()方法是静态方法,Method2()方法是非静态方法
package Synchronized.Seven.Phenomenon;
public class phenomenon6 implements Runnable{
static phenomenon6 instence = new phenomenon6();
//static修饰的背后'锁'是.class对象
public static synchronized void Method1() {
System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
//没有静态修饰,'锁'是t实例本身his对象.
public synchronized void Method2() {
System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
Method1();
}else{
Method2();
}
}
public static void main(String [] args){
Thread t1 = new Thread(instence);
Thread t2 = new Thread(instence);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("all is over!");
}
}
结论:静态synchronized修饰的方法和非静态synchronized修饰的方法,之间所获取到的 ’ 锁 ’ 是不相同的。所以两者之间没有影响。
1.7、方法抛出异常后,会释放锁
//
package Synchronized.Seven.Phenomenon;
public class Phenomenon7 implements Runnable{
static Phenomenon7 instence = new Phenomenon7();
//static修饰的背后'锁'是.class对象
public synchronized void Method1() {
System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
throw new Exception();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
//没有静态修饰,'锁'是t实例本身his对象.
public synchronized void Method2() {
System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
Method1();
}else{
Method2();
}
}
public static void main(String [] args){
Thread t1 = new Thread(instence);
Thread t2 = new Thread(instence);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("all is over!");
}
}
package Synchronized.Seven.Phenomenon;
public class Phenomenon7 implements Runnable{
static Phenomenon7 instence = new Phenomenon7();
//static修饰的背后'锁'是.class对象
public synchronized void Method1() {
System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
throw new RuntimeException();
//System.out.println(Thread.currentThread().getName()+"is over!");
}
//没有静态修饰,'锁'是t实例本身his对象.
public synchronized void Method2() {
System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is over!");
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
Method1();
}else{
Method2();
}
}
public static void main(String [] args){
Thread t1 = new Thread(instence);
Thread t2 = new Thread(instence);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("all is over!");
}
}
I’m a synchronized and static method,my name is:Thread-0
Exception in thread “Thread-0” I’m a synchronized method ,my name is:Thread-1
java.lang.RuntimeException at Synchronized.Seven.Phenomenon.Phenomenon7.Method1(Phenomenon7.java:13) at Synchronized.Seven.Phenomenon.Phenomenon7.run(Phenomenon7.java:29)
at java.lang.Thread.run(Thread.java:748)
Thread-1is over!
all is over!
结论:当方法中抛出了异常之后,JVM会帮助我们释放掉,synchronized获得的锁。以至于后序别的线程中的synchronized可以重新获取这把对象锁或类锁。
1.8、总结
1、一个锁只能同时被一个线程获取,没有拿到锁的线程必须等待。
2、每个实例都对应有自己的一把锁,不同实例之间互不影响;例如:当锁对象是 *.class 以及synchronized修饰的static方法的时候,所有的对象共用同一把类锁;
3、无论这个方法是正常执行完毕还是抛出了异常,都会释放掉自身持有的’锁’ ;