在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源
必须对这种潜在资源冲突进行预防
解决的办法:
在线程使用一个资源时为其加锁即可,访问资源的第一个线程为其加上锁后其他线程便不能再使用那个资源,
除非被解锁
sychronized有两种用法:
1修饰方法
2.像静态代码块一样
1.1 当synchronized关键字修饰一个方法是的时候,该方法叫做同步方法
synchronized方法是一种粗粒度的并发控制,某一时刻只能有一个线程执行该synchronized方法;
1.2 sychronized块写法
synchronized(obj){
}
表示线程在执行的时候会被Object对象上锁
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内,synchronized块之外的代码时是可以被多个线程同时访问到的
下面这段话很重要!!!
java中每个对象都有一把锁(lock)或者叫监视器(monitor)当访问某个对象的synchronized方法时,表示该对象上锁,此时其他任何线程都无法再去访问该synchronized方法了,直到之前的那个线程执行方法完毕后或者时抛出了异常那么该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法当一个线程去访问被synchronzied修饰的方法时候,该线程就会给方法所在的对象上锁第二线程想访问就会进不去,当第一线程执行完该方法第二线程才能进入该方法
如果一个对象有多个sychronized方法,某以时刻某个线程已经进入到了某个
sychronized方法,那么在该方法没有执行完毕前,其他线程是无法访问该对象的任何sychronized方法的
假设play2时static修饰的当一个线程去访问静态的并被sychronized修饰的方法时他锁的不是当前对象他锁的时当前对象的class对象
因为java中无论一个类有多少个对象这些对象对应唯一一个class对象,因此当线程分别访问同一个类的两个对象的两个staic,sychronized
方法时,他们的执行顺序也是有序的也就是说一个线程先去执行方法长记性王弼后另一个线程才开始执行
判断执行顺序关键看锁的是谁
public class SynchronizedDemo{
/**
*银行取钱的案例
*/
publicstaticvoidmain(String[]args){
Bankbank=newBank();
Waitw1=newWait(bank);
bank=newBank();
Waitw2=newWait(bank);
w1.start();
w2.start();
}
}
classBank{
//实例变量时
privateintmoney=1000;//加上static后所有的对象操纵的都是共享的这一个变量
//返回取到钱的数目number要取的钱数
publicintgetMoney(intnumber){
if(number<0){
return-1;
}
elseif(number>money){
return-2;
}elseif(money<0){
return-3;
}
{
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
money-=number;
System.out.println("剩余"+money);
returnnumber;
}
}
}
class Wait extends Thread{
privateBankbank;
publicWait(Bankbank){
this.bank=bank;
}
@Override
public void run(){
System.out.println(bank.getMoney(800));
}
}
importorg.junit.Test;
publicclassSynchronizedDemo02{
@Test
publicvoidtest(){
Ee=newE();
ThreadD1t1=newThreadD1(e);
//e=newE();
ThreadD2t2=newThreadD2(e);
t1.start();
t2.start();
}
}
classE{
publicsynchronizedvoidplay1(){
for(inti=0;i<20;i++){
System.out.println("play1-->"+i);
}
}
publicsynchronizedstaticvoidplay2(){
for(inti=0;i<20;i++){
System.out.println("play2-->"+i);
}
}
}
classThreadD1extendsThread{
privateEe;
ThreadD1(Ee){
this.e=e;
}
@Override
publicvoidrun(){
e.play1();
}
}
classThreadD2extendsThread{
privateEe;
ThreadD2(Ee){
this.e=e;
}
@Override
publicvoidrun(){
e.play2();
}
}
importorg.junit.Test;
publicclassSynchronizedDemo03{
@Test
publicvoidtest(){
EEe=newEE();
ThreadD3t1=newThreadD3(e);
//e=newE();
ThreadD4t2=newThreadD4(e);
t1.start();
t2.start();
}
}
classEE{
privateObjectobj=newObject();
//privateObjectobj2=newObject();
//想达到和锁在方法上一个效果就锁this
publicvoidplay1(){
synchronized(obj){
for(inti=0;i<20;i++){
System.out.println("play1-->"+i);
}
}
}
publicvoidplay2(){
synchronized(obj){
for(inti=0;i<20;i++){
System.out.println("play2-->"+i);
}
}
}
}
classThreadD3extendsThread{
privateEEe;
ThreadD3(EEe){
this.e=e;
}
@Override
publicvoidrun(){
e.play1();
}
}
classThreadD4extendsThread{
privateEEe;
ThreadD4(EEe){
this.e=e;
}
@Override
publicvoidrun(){
e.play2();
}