One of the developers investigated the problem and saw right away
what was going on. While there are different high-level ways to
characterize the bug (and we'll get to those in a moment), the bottom
line is that the code allows unfettered concurrent read/write access
to a shared myData variable, opening up the possibility
of a race condition:
readUserData() and sets this.myData.this.myData, there's a context switch. User B's thread comes in and sets a new value for this.myData.I think most developers (junior or otherwise) would understand the explanation I just gave.
I'm less optimistic about developers' ability to easily recognize the problem, especially absent a production issue. I think senior developers would recognize the problem on sight, and I even think that many midlevel developers (say with around three to five years of experience) would too. But many midlevel folks would not, and I think most junior developers wouldn't either.
And who might actually create the bug? Once again I think that senior developers would not do it, and I don't think that most midlevel developers would either, mostly because you wouldn't be able to get away with doing that for years on end.
Lots of junior developers could make the mistake though, mostly because junior developers usually have bad habits that they fail to recognize as such. In this case the habit would be to declare all or most variables as instance variables, which looks kind of neat in the source code, but reveals a fundamental lack of understanding of the OOP principle of encapsulation. Another bad habit I've seen (and, incidentally, one that similarly reveals a poor understanding of encapsulation) is people avoiding the use of package protected visibility in Java simply because there's no associated keyword; they'd rather use protected visibility, not realizing that they've just made an API commitment. (I alluded to this in the introduction.) Sometimes I think it would have been better if the creators of Java would have just come up with some keyword for package protected visibility.
While it could be argued that a "real" midlevel developer would never make mistakes like this, here I'm using "senior", "midlevel" and "junior" as convenient substitutes for years of experience, recognizing that they're not truly interchangeable. But in a way that's exactly my point. I'm claiming that there are plenty of people with three to five years of experience who might fail to recognize errors of the sort we're describing. And since there are lots of developers with three to five years of experience, I'm claiming that code like the above may not be as uncommon as people may think.