JavaConcurrency -2-Synchronized关键字

Synchronized是Java的关键字,同步锁
修饰对象由如下几种
1 修饰代码块,被修饰的代码块称为 同步语句块,锁作用的对象时调用该代码块的对象
2修饰方法,被修饰的方法称为同步方法,锁作用的对象 是 调用这个方法的对象
3修饰静态方法,锁作用的对象 是 这个类的所有对象。
4修饰类,锁作用的对象 是 这个类的所有对象。

代码转载于LovelyBear2019的博客
1 修饰代码块
一个线程访问一个对象的synchronized(this)修饰的代码块时,同一时间,其他试图访问该对象的线程将被阻塞
如下,当两个并发线程thread1 和thread2 访问同一个对象syncThread中的synchronized代码块时,在同一个时刻只能有一个线程得到执行,另一个线程收到阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。

 class SyncThread implements Runnable {
 	private static int count;
 	public SyncThread() {
 		count = 0;
 	}

 	public void run() {
 		synchronized (this) {
 			for (int i = 0; i < 5; i++) {
 				try {
 					System.out.println(Thread.currentThread().getName() + "-" + (count++));
 					Thread.sleep(100);
 				} catch (InterruptedException e) {
 					e.printStackTrace();
 				}
 			}
 		}
 	}

 	public int getCount() {
 		return count;
 	}
 }

 public class Synchronized_1 {
 	public static void main(String[] args) {
 		SyncThread syncThread = new SyncThread();
 		Thread thread1 = new Thread(syncThread, "SyncThread1");
 		Thread thread2 = new Thread(syncThread, "SyncThread2");
 		thread1.start();
 		thread2.start();
 	}
 }

结果为:

SyncThread1-0
SyncThread1-1
SyncThread1-2
SyncThread1-3
SyncThread1-4
SyncThread2-5
SyncThread2-6
SyncThread2-7
SyncThread2-8
SyncThread2-9

把调用当时改变一下:

Thread thread1 = new Thread(new SyncThread(), "SyncThread1");
Thread thread2 = new Thread(new SyncThread(), "SyncThread2");
thread1.start();
thread2.start();

结果为:

SyncThread1-0
SyncThread2-1
SyncThread2-2
SyncThread1-3
SyncThread2-4
SyncThread1-5
SyncThread2-6
SyncThread1-7
SyncThread2-8
SyncThread1-9

原因为:
这时候创建了两个SyncThread的对象syncThread1和syncThread2,线程thread1执行的是syncThread1对象中的synchronized代码(run),而线程thread2执行的是syncThread2对象中的synchronized代码(run)
会有两个锁,分别锁定syncThread1对象和syncThread2对象,而这两把锁是互不干扰的,不形成互斥,所以两个线程可以同时执行

可以给某个指定对象加锁:

class Account {
String name;
float amount;

public Account(String name, float amount) {
this.name = name;
this.amount = amount;
}
//存钱
public void deposit(float amt) {
amount += amt;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//取钱
public void withdraw(float amt) {
amount -= amt;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public float getBalance() {
return amount;
}
}
class AccountOperator implements Runnable{
	private Account account;
	public AccountOperator(Account account) {
		this.account = account;
	}

	public void run() {
		synchronized (account) {
			account.deposit(500);
			account.withdraw(500);
			System.out.println(Thread.currentThread().getName() +:+ account.getBalance());
		}
	}
}
public class Synchronized_4 {
	public static void main(String[] args) {
	Account account = new Account(“zhang san”, 10000.0f);
	AccountOperator accountOperator = new AccountOperator(account);

 	final int THREAD_NUM = 5;
 	Thread threads[] = new Thread[THREAD_NUM];
 	for (int i = 0; i < THREAD_NUM; i ++) {
 	   threads[i] = new Thread(accountOperator, "Thread" + i);
 	   threads[i].start();
 	}
 }

结果为:

Thread0:10000.0
Thread4:10000.0
Thread3:10000.0
Thread2:10000.0
Thread1:10000.0

用synchronized给account对象加了锁,当一个线程访问account对象时,其他试图访问account对象的线程将会阻塞,知道该线程访问account对象结束。谁再拿到那个锁的控制,就可以运行加锁代码

2 给方法加锁
两种写法等价,都是锁定了整个方法时的内容

 public synchronized void method() {
       // todo
 }
 
public void method() {
 	synchronized(this) {
 	   // todo
 	}
 }

注意:
synchronized来定义方法,但synchronized并不属于方法定义的一部分,因此synchronized关键字不能被继承。父类中的某个方法使用了synchronized关键字,而在子类中覆盖了这个方法,子类中这个方法默认情况下并不是同步的。子类要显示的加上synchronized关键字才可以。

class Parent {
      public synchronized void method() { }
 }
 class Child extends Parent {
      public synchronized void method() { }
 }

子类调用父类的同步方法,子类中方法依旧为同步方法:

class Parent {
     public synchronized void method() {   }
}
class Child extends Parent {
     public void method() { super.method();   }
}

3 修饰一个静态方法
静态方法是属于类的而不属于对象的。同样的,synchronized修饰的静态方法锁定的是这个类的所有对象

class SyncThread implements Runnable {
private static int count;

   public SyncThread() {
      count = 0;
   }

   public synchronized static void method() {
      for (int i = 0; i < 5; i ++) {
         try {
            System.out.println(Thread.currentThread().getName() + ":" + (count++));
            Thread.sleep(100);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   public synchronized void run() {
      method();
   }
}

public class Synchronized_5 {
	public static void main(String[] args) {
		SyncThread syncThread1 = new SyncThread();
		SyncThread syncThread2 = new SyncThread();
		Thread thread1 = new Thread(syncThread1, "SyncThread1");
		Thread thread2 = new Thread(syncThread2, "SyncThread2");
		thread1.start();
		thread2.start();
	}
}

结果为:

SyncThread1-0 
SyncThread1-1 
SyncThread1-2 
SyncThread1-3 
SyncThread1-4 
SyncThread2-5 
SyncThread2-6 
SyncThread2-7 
SyncThread2-8 
SyncThread2-9

4修饰一个类

class SyncThread implements Runnable {
   private static int count;

   public SyncThread() {
      count = 0;
   }

   public static void method() {
      synchronized(SyncThread.class) {
         for (int i = 0; i < 5; i ++) {
            try {
               System.out.println(Thread.currentThread().getName() + ":" + (count++));
               Thread.sleep(100);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }
   }

   public synchronized void run() {
      method();
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值