java:竞争条件 - 有没有办法确保几行代码一起执行?
我有一个注册页面,用于接收令牌并解析它们并在参数适用时登录用户。
在我检查令牌的时间到我从数据库中删除令牌的时间之间,另一个用户可以使用相同的令牌登录。有没有办法确保特定范围的代码行将在不受干扰的情况下执行,这样我就不会出现竞争条件问题?
谢谢
更新
我有两台服务器。
- apache tomcat 6
- red5 v0.9(免费的基于java的flash媒体流和通信服务器)
我正在为Facebook编写一个游戏应用程序。
游戏本身是用 adobe flash builder 2 编写的。
游戏本身将使用 red5 服务器提供服务。问题是 red5 没有收到请求和响应标头,因此无法检索会话信息以用于从 facebook 获取信息。
为了解决用户连接到 tomcat 服务器的问题,该页面检查会话中 facebook 相关信息,并使用tinyFBClient 连接到 facebook,并将信息存储在 mysql 数据库中(用户详细信息),以确保此同一用户是要连接到 red5 的用户。
一旦创建了令牌。 tomcat页面显示一个对象HTML元素,以显示相关的SWF文件(游戏文件)。 tomcat 页面将令牌传递给该 SWF 文件。加载 SWF 文件后,它会获取该令牌并使用它连接到 red5 并查找用户信息。
我希望描述可以帮助您了解我的需求。 感谢大家的支持!
I have a registration page that receives tokens ad parse them and login the user if the parameters apply.
Between the time that i checked the token, to the time that i removed the token from the db, another user can use the same token to login. is there a way to make sure that specific range of lines of code will be executed with not interference, so i won't have race condition problem ?
thanks
update
I have two servers.
- apache tomcat 6
- red5 v0.9 (free java based flash media streaming and communication server)
I'm writing a game application for Facebook.
the game itself is written in adobe flash builder 2.
the game itself will be served using the red5 server. the problem is that red5 does not receive the request and response headers and because of that cannot retrieve session information to use in order to fetch information from facebook.
to resolve the issue the user connect to the tomcat server, that page checks the session for facebook related information and uses tinyFBClient to connect to facebook, and to store the information in the mysql db (user details), in order to make sure that this same user is the user that's going to connect to red5.
once a token is created. the tomcat page displays an object HTML element in order to show the relevant SWF file (game file). the tomcat page passes the token to that SWF file. once the SWF file is loaded, it takes that token and uses it to connect to red5 and for it to find out the user information.
I hope that description helps you understand my needs.
thanks for all of your support!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以同步代码块,以便一次只有一个线程可以执行它。然而,这似乎不是一个很好的解决方案,因为它会减慢您的应用程序的速度。您希望多个用户同时登录。
代币是如何创建的?如果您要在服务器端生成它们以响应用户登录,那么一个用户不应该能够使用另一用户的令牌。
You could synchronize the block of code, such that only one thread at a time could execute it. However, this doesn't seem like a very good solution, as it will slow down your application. You would like to have multiple users logging in concurrently.
How are tokens created? If you were to generate them on the server side in response to a user logging in, then one user shouldn't be able to use another user's token.
您可以使用 Lock 对象。
使用 Lock 对象比更原始的同步块和方法有优势。
You could use a Lock object.
Using Lock objects has advantages over the more primitive synchronized blocks and methods.
听起来你需要一个同步方法/块:
请参见此处的示例(同步方法)
http://java.sun.com/docs/books/tutorial/essential/concurrency/syncmeth.html
注意不要煮过头!太多的同步可能会导致瓶颈!
Sounds like you need a synchronized method / block:
See here for example (synchronized method)
http://java.sun.com/docs/books/tutorial/essential/concurrency/syncmeth.html
Be careful not to over-cook it the otherway ! Too much synchronization can lead to bottlenecking !
我不确定您为什么要创建登录令牌。您的问题似乎暗示该令牌位于数据库中而不是内存中。如果是这样,同步和互斥体不会真正有帮助,您需要的是使用“选择更新”来锁定数据库记录。
也许这会带来很多不相关的复杂性,但是为什么要创建令牌来进行登录呢?每当我进行登录时,我只需从屏幕或传入表单中收集用户 ID 和密码,检查数据库以查看该组合是否有效,如果有效,则让用户进入。您需要令牌做什么?
I'm not sure why you're creating a token for a login. Your question seems to imply this token is on the database and not in memory. If so, synchronization and mutexes won't really help, what you need is to lock the database record with a "select for update".
Maybe this gets into a lot of irrelevant complexity, but why are you creating a token to do a login? Any time I do a login, I simply collect the userid and password from the screen or incoming form, check against the database to see if the combination is valid, and if so let the user in. What do you need a token for?
你说你“从数据库中删除令牌”。数据库是SQL数据库吗?如果是这样,那么您可以使用事务来避免竞争条件。它看起来像这样:
UUID sessionID = UUID.randomUUID();
DELETE FROM Tokens WHERE TokenID =
INSERT INTO Session VALUES (sessionUUID, userID, loginTime, ...)
现在,如果登录成功(即受影响的行计数恰好为 1),则向客户端发送包含会话 ID 的 cookie。
You say that you "remove the token from the db". Is the database a SQL database? If so then you can use a transaction to avoid the race condition. It would look something like this:
UUID sessionID = UUID.randomUUID();
DELETE FROM Tokens WHERE TokenID = <requested-token>
INSERT INTO Session VALUES (sessionUUID, userID, loginTime, ...)
Now if the login was successful (i.e. the affected row count was exactly 1), send the client a cookie containing the session ID.