1.同步函数:就是在函数上加上同步关键字(syschronized)进行修饰
同步函数使用的锁即this,调用该函数的对象(下面例子中的b)
同步有两种形式:
1)同步代码块
2.验证同步函数的锁是this
同步函数使用的锁即this,调用该函数的对象(下面例子中的b)
同步有两种形式:
1)同步代码块
2)同步函数
/*
class Bank
{
private int sum = 0;
private Object obj = new Object();
public void add(int money){
synchronized(obj){
sum = sum + money;
System.out.println("sum"+sum);
}//同步代码块
}
}
*/
class Bank
{
private int sum = 0;
public synchronized void add(int money){
sum = sum + money;
System.out.println("sum"+sum);
}//同步函数
}
class Customer implements Runnable
{
private Bank b = new Bank();
public void run(){
for(int i = 0;i < 3;i++){
b.add(100);
}
}
}
class BankDemo
{
public static void main(String[] args)
{
Customer c = new Customer();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
2.验证同步函数的锁是this
注意:静态(static)同步函数的锁是 类名.class
static方法随着类的加载,这时不一定有该类的对象,但一定有该类的字节码文件对象。
这个对象简单的表示为 类名.class
/**
验证同步函数的锁是this
思路:1)同步代码块使用明锁obj,同步函数使用this锁,如果执行同一个任务,
两线程将会出现不同步的现象。
2)将同步代码块的锁换成this,那么两线程将会同步
*/
class SaleTicket implements Runnable
{
private int tickets = 100;
Object obj = new Object();//synchronized(obj),相当于“锁”
//flag用于进程0-1间的切换
public boolean flag = true;
public void run(){
if(flag == true){
while(true){
synchronized(obj){//同步代码块
if(tickets > 0){
try{
Thread.sleep(10);//线程停止执行10ms
}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"..code.."+tickets--);
}
}
}
}
else
while(true)
this.sale();
}
//同步函数
public synchronized void sale(){
if(tickets > 0){
try{
Thread.sleep(10);//线程停止执行10ms
}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"..func.."+tickets--);
}
}
}
class TicketDemo
{
public static void main(String[] args) throws InterruptedException
{
SaleTicket t = new SaleTicket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
//main线程停止执行10ms,执行t1线程
Thread.sleep(10);
//切换到t2线程
t.flag = false;
t2.start();
}
}
3.单例模式的并发访问
/**
单例设计模式的并发访问
*/
/*
//恶汉式,不存在安全问题
class Single{
private static final Single s = new Single();
private Single(){}
public static Single getInstance(){
return s;
}
}
*/
//懒汉式
class Single{
private static Single s;
private Single(){};
public static Single getInstance(){
//双if结构,提高了判断锁的效率
if(s == null){
//同步代码块
synchronized(Single.class){
if(s == null){
s = new Single();
}
}
}
return s;
}
}
class SingleWork implements Runnable{
public void run (){
while(true){
Single.getInstance();
}
}
}
class SingleDemo{
public static void main(String[] args)
{
SingleWork w = new SingleWork();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
t1.start();
t2.start();
}
}
4.同步代码块和同步函数的区别
同步代码块可使用任意对象作为锁
同步函数只能使用this作为锁
5.死锁
/**
死锁:
场景一:
同步嵌套,即两个以上的锁相互嵌套成环
*/
class Task implements Runnable{
//flag用于两线程分别执行run中不同的代码块
private boolean flag;
Task(boolean flag){
this.flag = flag;
}
public void run(){
if(flag == true){
while(true){
synchronized(Mylock.locka){
System.out.println("if...locka");
synchronized(Mylock.lockb){
System.out.println("if...lockb");
}
}
}
}
else{
while(true){
synchronized(Mylock.lockb){
System.out.println("else...lockb");
synchronized(Mylock.locka){
System.out.println("else...locka");
}
}
}
}
}
}
//定义两个锁locka和lockb
class Mylock{
public static final Object locka = new Object();
public static final Object lockb = new Object();
}
class DeadlockDemo{
public static void main(String[] args){
Thread t1 = new Thread(new Task(true));
Thread t2 = new Thread(new Task(false));
t1.start();
t2.start();
}
}