synchronized作用:通过private关键字来保证数据对象仅可以被方法访问,所以提出同步方法,使进程有序,不会出错。加了synchronized的方法只有获得锁后才能执行,且执行直到结束后才释放,允许其他方法执行。
synchronized的两种使用方法:
1.同步方法:锁某一方法,public synchronized 函数名(){}
2.同步代码块:锁定某一方法不够时,可以锁某一块,
public 方法名(){
synchronized(进程操作的变量){具体操作}
}
死锁:多个线程互相抱着对方所需要的资源,形成僵持。
public class TestLock {
public static void main(String[] args) {
Makeup g1=new Makeup(0,"白雪公主");
Makeup g2=new Makeup(1,"王母娘娘");
g1.start();
g2.start();
}
}
//口红
class Lipsticks{}
//镜子
class Mirror{}
class Makeup extends Thread{
@Override
public void run() {
makeup();
}
//用static方法保证该资源仅有一份
static Lipsticks lipsticks=new Lipsticks();
static Mirror mirror=new Mirror();
int choice;//进行选择
String name;//选择人
Makeup(int choice,String name){//利用构造方法传参
this.choice=choice;
this.name=name;
}
public void makeup(){
if (choice==0) synchronized (lipsticks) {
System.out.println(this.name + "获得口红");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){
System.out.println(this.name+"获得镜子");
}
}//由于多线程,没有前后关系,使得g1锁住了口红,g2锁住了镜子。
//导致每个人的下一步都无法进行,这就是死锁,相互拥有对方所需资源。
else {
synchronized (mirror) {
System.out.println(this.name + "获得镜子");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipsticks){
System.out.println(this.name+"获得口号");
}
}
}
}
}
解决办法:
public void makeup(){
if (choice==0) synchronized (lipsticks) {
System.out.println(this.name + "获得口红");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}//将第二把锁,移出第一把锁内,这样g1锁住口红后,就结束释放了,g2同理
//均释放出资源。则可执行成功
synchronized (mirror){
System.out.println(this.name+"获得镜子");
}
}
else {
synchronized (mirror) {
System.out.println(this.name + "获得镜子");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){
System.out.println(this.name+"获得口红");
}
}
}
}
锁的另一种方式:Lock
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
Method m1=new Method(5);
new Thread(m1,"张1").start();
new Thread(m1,"张2").start();
new Thread(m1,"张3").start();
new Thread(m1,"张4").start();
new Thread(m1,"张5").start();
new Thread(m1,"张6").start();
new Thread(m1,"张7").start();
new Thread(m1,"张8").start();
}
}
class Method implements Runnable{
int num;
private final ReentrantLock lock=new ReentrantLock();
public Method(int num){
this.num=num;
}
@Override
public void run() {
try {
lock.lock();
if (num!=0){
System.out.println(Thread.currentThread().getName()+"拿到了"+num--+"章票");
}
}finally {
lock.unlock();
}
}
}