方法1:用mysql命令锁住表.
成都创新互联专注为客户提供全方位的互联网综合服务,包含不限于成都做网站、网站制作、大渡口网络推广、成都微信小程序、大渡口网络营销、大渡口企业策划、大渡口品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联为所有大学生创业者提供大渡口建站搭建服务,24小时服务热线:18982081108,官方网址:www.cdcxhl.com
public void test() {
String sql = "lock tables aa1 write";
// 或String sql = "lock tables aa1 read";
// 如果想锁多个表 lock tables aa1 read ,aa2 write , .....
String sql1 = "select * from aa1 ";
String sql2 = "unlock tables";
try {
this.pstmt = conn.prepareStatement(sql);
this.pstmt1 = conn.prepareStatement(sql1);
this.pstmt2 = conn.prepareStatement(sql2);
pstmt.executeQuery();
pstmt1.executeQuery();
pstmt2.executeQuery();
} catch (Exception e) {
System.out.println("异常" + e.getMessage());
}
}
对于read lock 和 write lock官方说明:
1.如果一个线程获得一个表的READ锁定,该线程(和所有其它线程)只能从该表中读取。
如果一个线程获得一个表的WRITE锁定,只有保持锁定的线程可以对表进行写入。
其它的线程被阻止,直到锁定被释放时为止。
2.当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。
虽然使用LOCKTABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。
同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,
在此情况下,您必须分别获得对每个别名的锁定。
对与read lock 和 write lock个人说明:
1.read lock 和 write lock 是线程级(表级别).
2.在同一个会话中加了read lock锁. 只能对这个表进行读操作.对这个表以外的任何表都无法进行增、删、改、查的操作.
但是在不同会话中,只能对加了read lock的表进行读操作.但可以对read lock以外的表进行增、删、改、查的操作.
3.在同一个会话中加了write lock锁.只能对这个表进行读、写操作.对这个表以外的任何表都无法进行增、删、改、查的操作.
但是在不同会话中,无法对加了write lock的表进行读、写操作.但可以对write lock以外的表进行增、删、改、查的操作.
4.如果表中使用了别名.(SELECT * FROM aa1 AS byname_table)
在对aa1加锁时,必须把别名加上去(lock tables aa1 as byname_table read)
在同一个会话中.必须使用别名进行查询.
在不同的会话中.可以不需要使用别名进行查询.
5.在多个会话中可以对同一个表进行lock read操作.但不能在多个会话中对同一个表进行lock write操作(这些锁将等待已锁的表释放自身的线程锁)
如果多个会话对同一个表进行lock read操作.那么在这些会话中,也只能对以锁的表进行读操作.
6.如果要你锁住了一个表,需要嵌套查询.你必须使用别名,并且,要锁定别名.
例如.lock table aa1 read ,aa1 as byname_table read;
select * from aa1 where id in (select * from aa1 as xx where id=2);
7.解锁必须用unlock tables;
另:
在JAVA程序中,要想解锁,需要调用 unlock tables来解锁.
如果没有调用unlock tables.
关闭connection 、程序结束 、调用GC 都能解锁.
方法2:用记录锁锁表.
public void test() {
String sql = "select * from aa1 for update";
// select * from aa1 lock in share mode;
try {
conn.setAutoCommit(false);
this.pstmt = conn.prepareStatement(sql);
pstmt.executeQuery();
} catch (Exception e) {
System.out.println("异常" + e.getMessage());
}
}
1.for update 与 lock in share mode 属于行级锁和页级锁
2.for update 排它锁,lock in share mode 共享锁
3.对于记录锁.必须开启事务.
4.行级锁定事实上是索引记录的锁定.只要是用索引扫描的行(或没索引全表扫描的行),都将被锁住.
5.在不同的隔离级别下还会使用next-key locking算法.即所扫描的行之间的“间隙”也会也锁住(在Repeatable read和Serializable隔离级别下有间隙锁).
6.在mysql中共享锁的含义是:在被共享锁锁住的行,即使内容被修改且并没有提交.在另一个会话中依然看到最新修改的信息.
在同一会话中加上了共享锁.可以对这个表以及这个表以外的所有表进行增、删、改、查的操作.
在不同的会话中.可以查到共享锁锁住行的最新消息.但是在Read Uncommitted隔离级别下不能对锁住的表进行删,
改操作.(需要等待锁释放才能操作...)
在Read Committed隔离级别下不能对锁住的表进行删,改操作.(需要等待锁释放才能操作...)
在Repeatable read隔离级别下不能对锁住行进行增、删、改操作.(需要等待锁释放才能操作...)
在Serializable隔离级别下不能对锁住行进行增、删、改操作. (需要等待锁释放才能操作...)
7.在mysql中排他锁的含义是:在被排它锁锁住的行,内容修改并没提交,在另一个会话中不会看到最新修改的信息。
在不同的会话中.可以查到共享锁锁住行的最新消息.但是Read Uncommitted隔离级别下不能对锁住的表进行删,
改操作.(需要等待锁释放才能操作...)
在Read Committed隔离级别下不能对锁住的表进行删,改操作.(需要等待锁释放才能操作...)
在Repeatable read隔离级别下不能对锁住行进行增、删、改操作.(需要等待锁释放才能操作...)
在Serializable隔离级别下不能对锁住行进行增、删、改操作. (需要等待锁释放才能操作...)
8.在同一个会话中的可以叠加多个共享锁和排他锁.在多个会话中,需要等待锁的释放.
9.SQL中的update 与 for update是一样的原理.
10.等待超时的参数设置:innodb_lock_wait_timeout=50 (单位秒).
11.任何可以触发事务提交的命令,都可以关闭共享锁和排它锁.
1.凡使用synchronized标记的方法,比如 public synchronized void func1() { .... },则同时只有一个线程能够运行这个方法。比如,线程1正在运行func1,则其他线程需要运行func1的话,会卡住,等线程1运行func1结束后,其他线程中,才会有一个幸运儿成功争取到运行func1的资格,然后这个幸运儿线程开始运行func1。没有争取到运行资格的其他线程,会继续等待。
2.你的例子中,被锁定的是 方法 m1,而不是属性b。所以,m1的synchronized加锁操作,与b没有半点毛钱关系。
3.要实现你的锁b想法,其实很简单。去买一件贞操宝甲来就行了。开玩笑,哈哈。要锁b,把main方法里的tt.m2()修改为tt.m1()。
4.以后别用“b”作为变量,总觉得怪怪了。也许你现在还没长大,很单纯。但大人的世界里,“b”是一种不文雅但又对人类的未来有重要作用的东西。建议用cb来代替b。
对象是一个锁标志。按照先到先得的原则,如果有多个线程都会执行代码,并使用同一个对象作为锁,
synchronize(对象){ .... }
那么,先执行这段代码的那个线程,将会获得这个对象锁,而当这个线程执行这段代码的时候,其他线程也是使用这个对象作为锁的,就不能执行这段代码,知道最初得到这个锁的线程运行完这段代码,然后再把锁分配给下一个线程执行。
Java中文件加锁机制如下:
在对文件操作过程中,有时候需要对文件进行加锁操作,防止其他线程访问该文件。对文件的加锁方法有两种:
第一种方法:使用RandomAccessFile类操作文件。
在java.io.RandomAccessFile类的open方法,提供了参数实现独占的方式打开文件:
RandomAccessFile raf = new RandomAccessFile(file, "rws");
其中的“rws”参数,rw代表读取和写入,s代表了同步方式,也就是同步锁。这种方式打开的文件,就是独占方式的。
第二种方法:使用sun.nio.FileChannel对文件进行加锁。
代码:
RandomAccessFile raf = new RandomAccessFile("file.txt", "rw");
FileChannel fc = raf.getChannel();
FileLock fl = fc.tryLock();
if(fl.isValid())
System.out.println("You have got the file lock.");
以上是通过RandomAccessFile来获得文件锁的,方法如下:
代码:
FileOutputStream fos = new FileOutputStream("file.txt");
FileChannel fc = fos.getChannel(); //获取FileChannel对象
FileLock fl = fc.tryLock(); //or fc.lock();
if(null != fl)
System.out.println("You have got file lock.");
//TODO write content to file
//TODO write end, should release this lock
fl.release(); //释放文件锁
fos.close; //关闭文件写操作
如果在读文件操作的时候,对文件进行加锁,操作过程如下:
FileChannel也可以从FileInputStream中直接获得,但是这种直接获得FileChannel的对象直接去操作FileLock会报异常NonWritableChannelException,需要自己去实现getChannel方法,代码如下:
private static FileChannel getChannel(FileInputStream fin, FileDescriptor fd) {
FileChannel channel = null;
synchronized(fin){
channel = FileChannelImpl.open(fd, true, true, fin);
return channel;
}
}
其实,看FileInputStream时,发现getChannel方法与我们写的代码只有一个地方不同,即open方法的第三个参数不同,如果设置为false,就不能锁住文件了。缺省的getChannel方法,就是false,因此,不能锁住文件。
与java无关,要用sql语句实现
前提目标表要有索引,查询要开启事物,使用select * from tb with(updlock) where col = xxx将一行数据锁住,其他连接不能再修改表
你的代码我没看,也没运行。
但我可以很明确的告诉你,你是没有办法控制线程的执行顺序的,不知道你学没学操作系统,等你学了线程调度你就知道为什么了,多线程的一个特点就是不可重现性。像sleep这些函数只能在一定程度上控制你的线程执行,但根本不是绝对的。因为当线程1在sleep时,系统也不一定会调用另一线程。
还有加锁也不是为了控制线程的执行顺序,它的目的是为了保护共享的互斥资源。